【问题标题】:AES 128 Compatibility between android and Objective Candroid 和 Objective C 之间的 AES 128 兼容性
【发布时间】:2016-07-25 23:30:36
【问题描述】:

我有两个应用程序:Android 和 iOS (Objective-C)。我正在尝试实施和加密系统,以便我可以在两个应用程序上加密并在服务器应用程序中解密。问题是我使用的是 AES128-ECB 但我从 android 获得的 base64 密钥与我的目标 c 密钥不匹配。我不知道我错过了什么。

这里是sn-ps: IOS

- (NSData*) EncryptAES: (NSString *) key{
char keyPtr[kCCKeySizeAES128+1];
bzero( keyPtr, sizeof(keyPtr) );

[key getCString: keyPtr maxLength: sizeof(keyPtr) encoding:NSUTF8StringEncoding];
size_t numBytesEncrypted = 0;

NSUInteger dataLength = [self length];

size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
const unsigned char iv[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

CCCryptorStatus result = CCCrypt( kCCEncrypt,
                                 kCCAlgorithmAES128,
                                 kCCOptionPKCS7Padding,
                                 keyPtr,
                                 kCCKeySizeAES128,
                                 iv,
                                 [self bytes], [self length],
                                 buffer, bufferSize,
                                 &numBytesEncrypted );

if( result == kCCSuccess )
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
else {
    NSLog(@"Failed AES");
}
return nil;
}

然后:

NSString *pass = @"WORD_TO_ENCRYPT";
NSString *key = @"STRING_KEY";

//Encryption - APPROACH 1
NSData *data = [pass dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [data EncryptAES:key];
NSString* encryptedBase64 = [self Base64Encode:encryptedData];

NSLog(@"%@", encryptedBase64);

这是我的 Java 函数:

    String plainTextKey = "STRING_KEY";
    String plainText = "WORD_TO_ENCRYPT";
    // Encrypt where jo is input, and query is output and ENCRPYTION_KEy is key
    //String inputtt = "some clear text data";
    byte[] input = new byte[0];
    String skyKey;

    input = plainText.getBytes("utf-8");
    MessageDigest md;
    md = MessageDigest.getInstance("MD5");
    byte[] thedigest = md.digest(plainTextKey.getBytes("UTF-8"));
    SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skc);
    byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
    ctLength += cipher.doFinal(cipherText, ctLength);
    String encode = Base64.encode(cipherText);
    System.out.println(encode);

我正用头撞墙,却不知道自己错过了什么。 提前感谢您的帮助!

PS:我没有任何特别的理由使用 AES128-ECB。如果多系统兼容性更简单,我可以使用任何其他算法。

【问题讨论】:

  • 那你为什么不直接使用 RNCryptor 呢?它具有必要的兼容性,并且比此代码更安全。
  • 在我看来,您在 Obj-C 中使用的是 ECB 模式。您应该将 Java 代码更改为 CBC 模式。
  • 一般建议:始终使用完全限定的密码字符串。 Cipher.getInstance("AES"); 可能会产生不同的密码,具体取决于默认的安全提供程序。它最有可能导致"AES/ECB/PKCS5Padding",但并非必须如此。如果它发生变化,您将失去不同 JVM 之间的兼容性。
  • 切勿使用ECB mode。它是确定性的,因此在语义上不安全。您至少应该使用像CBCCTR 这样的随机模式。最好对您的密文进行身份验证,以免像padding oracle attack 这样的攻击是不可能的。这可以通过 GCM 或 EAX 等认证模式或encrypt-then-MAC 方案来完成。
  • 加密成功了吗,iOS和Android结果不一样?还是加密失败?请提供更多详细信息。

标签: java android ios encryption aes


【解决方案1】:

在Android端,初始化Cipher实例时,必须提供匹配的IV。

byte[] iv = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
cipher.init(Cipher.ENCRYPT_MODE, skc, new IvParameterSpec(iv));

【讨论】:

    【解决方案2】:

    避免使用硬编码的 IV 作为加密机制,至少在 Android 上是这样。建议使用随机数生成器,但如果您不能提供随机值,至少从密钥构建 IV。

    另一方面,如果所有内容都来自密码,那么您将无法获得良好的安全性; 您需要在每条消息中添加一些随机性。

    确保存储加密期间使用的 IV,以便您可以正确地将其应用回解密。

    byte[] iv = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    cipher.init(Cipher.ENCRYPT_MODE, skc, new IvParameterSpec(iv));
    

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多