在 Objective C、.net 和 Android 中生成相同的加密字符串 AES/CBC/PKCS7Padding

Posted

技术标签:

【中文标题】在 Objective C、.net 和 Android 中生成相同的加密字符串 AES/CBC/PKCS7Padding【英文标题】:Generate same encrypted string AES/CBC/PKCS7Padding in Objective C, .net and Android 【发布时间】:2020-12-17 08:09:40 【问题描述】:

我想在 ios 中生成相同的加密字符串,在 .net 中生成 android。我可以在 android 和 .net 中生成相同的字符串,但在 Objective C 中则不同。

安卓代码:

public static String encrypt(String key, String value) 
    try 
        SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
        AlgorithmParameterSpec iv = new IvParameterSpec(key.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        return new String(Base64.encode(cipher.doFinal(value.getBytes("UTF-8")), Base64.NO_WRAP));

     catch (Exception e) 
        e.printStackTrace();
    
    return null;

后端代码

public Encryption(input: string): any 

return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(input), this.Cryptokey,



    keySize: 128 / 8,

    iv: this.iv,

    mode: CryptoJS.mode.CBC,

    padding: CryptoJS.pad.Pkcs7

);

在 Objective C 代码中

- (NSData *)AES256EncryptWithKey:(NSString *)key

// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [self length];

//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES256,
                                      NULL /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);
if (cryptStatus == kCCSuccess) 
    //the returned NSData takes ownership of the buffer and will free it on deallocation
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];


free(buffer); //free the buffer;
return nil;

我关注了这些网址 Encrypt AES/CBC/PKCS7Padding

How to encrypt with AES 256 CBC in Objective C

AES CBC Encryption With PKCS7Padding Has Different Results In Java And Objective-C

根据我对 Objective C 的理解,首先我需要转换 NSData 中的密码,然后将其传递给 AES 加密方法。 此方法将返回给我加密的数据,现在我需要将其转换为 base 64 字符串编码。 谁能向我建议我应该怎么做才能为 iOS、Android 和 .net 生成相同的结果?

例如 如果我想在所有 3 个平台上加密字符串“xceedancce”并且我的密钥是 7061737323313233

然后在 Android 和 .net 中,结果是 "uXDlYA4e8Z8HWd9rvNdXaw==" 相同,但在 iOS 中

它是“l4zDDnwOVJ0dz2fl7HdKIA==” 谁能建议我应该在 Objective C 中做什么?

谢谢。

【问题讨论】:

只是争辩说我不熟悉objective-c,但在Java中你使用key.getBytes作为你的IV的输入,在objective-c中你将iv设置为'NULL',这似乎是错的。也许你也可以使用'keyPtr'? 谢谢@MichaelFehr 我尝试在 Android 和 Objective C 中提供相同的 iv,但得到不同的结果。 @zaph 你能帮我这个谢谢。 这种加密非常不安全。它正在重用 IV,将密钥用作 IV,错误地生成了密钥,并且密钥的长度对于请求的加密来说是错误的。如果您可以替换它,请不要使用此代码。我专门在大量平台上构建了 RNCryptor,因为人们经常犯这些错误。但是,您没有得到您期望的原因是您传递了一个不同的 IV(正如迈克尔指出的那样),并且您传递了一个 128 位“密钥”(不是真正的密钥),但随后要求 256-位加密(kCCKeySizeAES256)。你的意思是 kCCKeySizeAES128。 如果您的所有加密都为相同的明文和密钥生成相同的输出,那么您就知道您的系统不安全。根据设计,加密系统会注入一些随机数据,例如 IV,因此相同的消息 + 密钥每次都会创建不同的输出。 AES-CBC 中 IV 的全部意义在于是一个额外的随机值。 【参考方案1】:

谢谢你,罗伯。我对(Objective C 和 C#)都使用了 RNCryptor 库,它解决了我的问题。

这是我的目标 C 代码:

-(NSString *)encryptUsingRNCryptor:(NSString *)strPassword

NSData *data = [strPassword dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSData *encryptedData = [RNEncryptor encryptData:data
                                    withSettings:kRNCryptorAES256Settings
                                          password:kKeyForEncryption
                                             error:&error];
NSString *encryptString = [encryptedData base64EncodedStringWithOptions:0];

NSLog(@"enccrypted data ----->>>## %@ ## %@", encryptedData, encryptString);

// Decryption

NSData *decryptedData = [RNDecryptor decryptData:encryptedData
                                    withPassword:kKeyForEncryption
                                           error:&error];
NSString *decodedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];

NSLog(@" Decryted data ----%@ --------and string %@", decryptedData, decodedString);

return [encryptedData base64EncodedStringWithOptions:0];

对于 C# 解密,我们使用了 RNCryptor-cs 库。

再次感谢罗伯:)

【讨论】:

嗨,chandini,您是否能够通过使用 RNCRYPTOR 为 android 和 iOS 获得正确的解密值?如果是,你能告诉你你用的是什么安卓吗? 我只在 iOS 上使用了这个库

以上是关于在 Objective C、.net 和 Android 中生成相同的加密字符串 AES/CBC/PKCS7Padding的主要内容,如果未能解决你的问题,请参考以下文章

来自 Swift 应用程序的 Objective C 库中定义的引用类型

在 Mac OS X 上结合 Objective-C 和 C/C++

objective-c和Cpp怎么混合编程?

iOS-Objective-C对象之类对象和元类对象

Objective-C学习笔记-第二天

objective-c入门