java – AES加密Android < - > iOS不同的结果,消息长度>
发布时间:2020-12-15 04:14:56 所属栏目:Java 来源:网络整理
导读:我在理解两个设备上的密码/加密器时遇到了一个真正的问题. 1. 如果我们使用Cipher AES加密iOS和Android上的消息并且字符串的charlength不大于16(例如“abcdefghijklmno”),我们在使用相同的密钥/密码加密后得到相同的结果. 2. 但是如果需要更长的消息,我们会
我在理解两个设备上的密码/加密器时遇到了一个真正的问题.
1. 2. 我做了很多研究如何为这两种设备获得相同的参数,起初我认为它是安全的. 这是我用于加密的密码: public String encode(Context context,String password,String text) throws NoPassGivenException,NoTextGivenException { if (password.length() == 0 || password == null) { throw new NoPassGivenException("Please give Password"); } if (text.length() == 0 || text == null) { throw new NoTextGivenException("Please give text"); } try { SecretKeySpec skeySpec = getKey(password); byte[] clearText = text.getBytes("UTF8"); //IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID final byte[] iv = new byte[16]; Arrays.fill(iv,(byte) 0x00); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); // Cipher is not thread safe //EDITED AFTER RIGHT ANSWER FROM //*** Cipher cipher = Cipher.getInstance("AES"); ***// // TO Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE,skeySpec,ivParameterSpec); String encrypedValue = Base64.encodeToString( cipher.doFinal(clearText),Base64.DEFAULT); Log.d(TAG,"Encrypted: " + text + " -> " + encrypedValue); return encrypedValue; } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } return ""; } public SecretKeySpec getKey(String password) throws UnsupportedEncodingException { int keyLength = 128; byte[] keyBytes = new byte[keyLength / 8]; // explicitly fill with zeros Arrays.fill(keyBytes,(byte) 0x0); // if password is shorter then key length,it will be zero-padded // to key length byte[] passwordBytes = password.getBytes("UTF-8"); int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length; System.arraycopy(passwordBytes,keyBytes,length); SecretKeySpec key = new SecretKeySpec(keyBytes,"AES"); return key; } 这是我的同事的iOS挂件: - (NSData *)AES128EncryptWithKey:(NSString *)key { // 'key' should be 32 bytes for AES256,// 16 bytes for AES256,will be null-padded otherwise char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused) bzero(keyPtr,sizeof(keyPtr)); // fill with zeroes (for padding) // insert key in char array [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; // the encryption method,use always same attributes in android and iPhone (f.e. PKCS7Padding) CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,kCCAlgorithmAES128,kCCOptionPKCS7Padding,keyPtr,kCCKeySizeAES128,NULL /* initialization vector (optional) */,[self bytes],dataLength,/* input */ buffer,bufferSize,/* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; } 我真的很想了解差异是什么以及如何避免它.与更大的字符串超过15个字符的测试给了我一个提示,但我不知道为什么:) 先谢谢你们! 解决方法
检查两个系统上正在使用的填充.不同的填充将导致不同的输出.不要依赖默认值,而是明确设置两侧的填充.您的第二个代码片段显式设置PKCS7填充.在两端使用它.
作为一般规则,不要依赖于不同系统之间的默认值.明确设置IV,模式,填充,随机数或其他任何需要的东西.即使最微小的细节不匹配,加密也会失败. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |