2013-03-13 123 views
6

我正试图在Android上实现AES128加密。我有一个解决方案,使用Objective C工作在iPhone上,但无法将其移植到Android。我已经搜索了一个解决方案的stackoverflow,但我似乎做错了什么。我对Java相当陌生,所以我想我错过了一些与数据,字符串转换有关的事情。Android AES 128加密

这里是我的iPhone加密:

char keyPtr[kCCKeySizeAES128+1]; 
[keyString getCString:keyPtr 
      maxLength:sizeof(keyPtr) 
      encoding:NSASCIIStringEncoding]; 

// CString for the plain text 
char plainBytes[[plainString length]+1]; 
[plainString getCString:plainBytes 
       maxLength:sizeof(plainBytes) 
       encoding:NSASCIIStringEncoding]; 

size_t bytesEncrypted = 0; 

// Allocate the space for encrypted data 
NSUInteger dataLength = [plainString length]; 
size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void* buffer = malloc(bufferSize); 

// Encrypt 
CCCryptorStatus ret = CCCrypt(kCCEncrypt, 
           kCCAlgorithmAES128, 
           kCCOptionPKCS7Padding | kCCOptionECBMode, 
           keyPtr, 
           kCCKeySizeAES128, 
           NULL, 
           plainBytes, sizeof(plainBytes), 
           buffer, bufferSize, 
           &bytesEncrypted); 
if (ret != kCCSuccess) { 
    free(buffer); 
} 

encryptedData = [NSData dataWithBytes:buffer length:bytesEncrypted]; 

这里是我的Java:

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8")); 

使用相同的密钥和明文的iPhone和Java给出不同的结果。我的iPhone结果以我需要的方式工作,所以我试图让java给我iPhone结果。我在Java中遗漏了一些东西,只是不确定它是什么。

编辑

基于下面的建议我修改我的Java这个

byte[] keyBytes = plainTextKey.getBytes("US-ASCII"); 
    SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES"); 
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    byte[] encrypted = cipher.doFinal(plainText.getBytes("US-ASCII")); 

但我仍然除了编码获得Android和iPhone

+3

你的编码是明文不同。 Android使用UTF8,iPhone使用ASCII。 – vcsjones 2013-03-13 16:08:21

+1

作为一个方面说明,我会劝阻你的密码模式使用ECB(除非你试图保持与已经使用它的系统的兼容性)。它使得识别加密数据中的模式变得相当容易。 – vcsjones 2013-03-13 16:10:49

+0

感谢vcsjones,我已将代码更新为plainText.getBytes(“ASCII”),但结果仍然不同 – Pabs 2013-03-13 16:37:58

回答

4

之间不同的结果您的明文存在困难(如注释中指出的vcsjones),请确保密钥字符串的编码相同(请注意,使用原始字符串,像密码,直接作为加密密钥是坏消息,使用密码派生函数,如密码中的PBKDF2来获得密钥)。

此外,用于ASCII的Java编码字符串是US-ASCII,而不仅仅是ASCII,因此请确保在getBytes调用中使用该编码字符串。

编辑:发现你的问题:iOS字符串在最后加上一个额外的空字符(0x00),而java不是。因此,在java中加密“hello world \ 0”会给你输出与“你好世界”在iOS中一样的输出

+0

感谢您的提示,我完全错过了“US-ASCII”。不幸的是问题仍然是一样的。我了解EBC的问题,但在这种特殊情况下,我需要使用它。我也更新了代码,使用“US-ASCII”既明文和密钥,但仍然是相同的结果。 – Pabs 2013-03-13 17:40:37

+0

@Pabs看到我的编辑 - 我想通了你的问题 – 2013-03-13 18:35:58

+0

甜蜜!感谢彼得,这完美无缺! – Pabs 2013-03-13 19:51:19

0

因特网上的大多数例子都是AES的弱执行。为了实现强壮,应随时使用随机IV,密钥应该散列。

更安全(随机IV +哈希键)跨平台(Android,iOS设备的C#)实现AES的在这里看到我的回答 - https://stackoverflow.com/a/24561148/2480840