本文介绍了在IOS中实现AES256加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的java代码。现在我想在Objective-C中实现相同的功能。

 加密加密密码; 
IvParameterSpec iv = new IvParameterSpec(key);
SecretKeySpec skeySpec = new SecretKeySpec(key,AES);
encryptCipher = Cipher.getInstance(AES / CBC / PKCS5Padding);
encryptCipher.init(Cipher.ENCRYPT_MODE,skeySpec,iv);
byte [] encrypted = encryptCipher.doFinal(dataToEncrypt.getBytes());
Log.d(TAG,encrypted string:
+ Base64.encodeToString(encrypted,Base64.DEFAULT));
返回Base64.encodeToString(加密,Base64.DEFAULT).trim();

这是我的iOS实现

   - (NSData *)AES256EncryptWithKey :( NSString *)键
{
char keyPtr [kCCKeySizeAES256 + 1];
bzero(keyPtr,sizeof(keyPtr));
[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;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES256,
NULL,
[self bytes]
dataLength,
buffer,
bufferSize,
& numBytesEncrypted);

if(cryptStatus == kCCSuccess)
{

return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer);
return nil;
}

这是我的哈希键生成功能。这个函数在android和ios中返回相同的键

  int dkLen = 16; 
NSData * keyData = [hash_key dataUsingEncoding:NSUTF8StringEncoding];
NSData * salt = [saltKey dataUsingEncoding:NSUTF8StringEncoding];
uint rounds = 1000;
uint keySize = kCCKeySizeAES128;

NSMutableData * derivedKey = [NSMutableData dataWithLength:keySize];





CCKeyDerivationPBKDF(kCCPBKDF2,// algorithm
keyData.bytes,// password
keyData.length, // passwordLength
salt.bytes,// salt
salt.length,// saltLen
kCCPRFHmacAlgSHA1,// PRF
rounds,// rounds
derivKey.mutableBytes ,// derivedKey
dkLen * 8);
return derivedKey;

我得到不同的输出。我做错了什么?答案是帮助我找出来。

解决方案

一个问题是Java代码使用CBC模式, iOS代码使用ECB模式。



接下来,从引用的项目:

// result = yHbhApwTpQ2ZhE97AKF / g = =

无效的Base64,它不包含4个字节的倍数。



使用以下选项:CBC,PKCS#7填充

 
输入:
数据:hello,它将被填充到16字节的块长度
键:
base64:VQQhu + dUdqXGoE7RZL2JWg ==
hex:550421bbe75476a5c6a04ed164bd895a
iv:
base64:VQQhu + dUdqXGoE7RZL2JWg ==
hex:550421bbe75476a5c6a04ed164bd895a
加密输出:
hex:ff21db840a704e943666113dec0285fe
base64:/ yHbhApwTpQ2ZhE97AKF / g ==

这是测试代码:

  NSString * base64Key = @VQQhu + dUdqXGoE7RZL2JWg ==; 
NSString * dataString = @hello;

NSData * key = [[NSData alloc] initWithBase64EncodedString:base64Key options:0];
NSData * data = [dataString dataUsingEncoding:NSUTF8StringEncoding];

NSLog(@key:%@,key);
NSLog(@data:%@,data);

NSData * encryptedData = [TestClass crypt:data
iv:key
key:key
上下文:kCCEncrypt];

NSLog(@encryptedData:%@,encryptedData);
NSString * encryptedBase64Data = [encryptedData base64EncodedStringWithOptions:0];
NSLog(@encryptedBase64Data:%@,encryptedBase64Data);

这是加密方法(在类 TestClass iv :((NSData *))$($)$($)$ iv
key:(NSData *)symmetricKey
上下文:(CCOperation)encryptOrDecrypt
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0; //移动到缓冲区的字节数。
NSMutableData * dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
symmetricKey.bytes,
kCCKeySizeAES128,
iv.bytes,
dataIn.bytes,
dataIn.length,
dataOut.mutableBytes,
dataOut.length,
& cryptBytes);

if(ccStatus!= kCCSuccess){
NSLog(@CCCrypt status:%d,ccStatus);
}

dataOut.length = cryptBytes;

return dataOut;
}

注意:我不断分开加密和数据转换。如果您使用在线加密实现,则填充将可能不是PKCS#7,因为mcrypt不支持它,而是它做非标准的空填充。由于pad字节只是pad字节的计数,所以可以在输入中模拟填充。以下是使用



请注意,填充为16个字节的块大小的helloPKCS#7添加了11个字节的uint8值11或 0x0B 68656c6c6f0B0B0B0B0B0B0B0B0B0B0B



最后问题仍然是为什么Java代码不会产生这个结果?


This is my java code. Now I want to implement same functionality in Objective-C.

Cipher encryptCipher;
IvParameterSpec iv = new IvParameterSpec(key);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = encryptCipher.doFinal(dataToEncrypt.getBytes());
Log.d("TAG", "encrypted string:"
        + Base64.encodeToString(encrypted, Base64.DEFAULT));
return Base64.encodeToString(encrypted, Base64.DEFAULT).trim();

This is my iOS implementation

- (NSData *)AES256EncryptWithKey:(NSString*)key
{
    char keyPtr[kCCKeySizeAES256 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [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;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                  kCCAlgorithmAES128,
                                  kCCOptionPKCS7Padding,
                                  keyPtr,
                                  kCCKeySizeAES256,
                                  NULL,
                                  [self bytes],
                                  dataLength,
                                  buffer,
                                  bufferSize,
                                  &numBytesEncrypted);

    if (cryptStatus == kCCSuccess)
    {

        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer);
    return nil;
}

This is my hash key generating function. this function return same key in android and ios

int dkLen = 16;
    NSData *keyData = [hash_key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *salt    = [saltKey dataUsingEncoding:NSUTF8StringEncoding];
    uint    rounds  = 1000;
    uint    keySize = kCCKeySizeAES128;

    NSMutableData *derivedKey = [NSMutableData dataWithLength:keySize];





    CCKeyDerivationPBKDF(kCCPBKDF2,               // algorithm
                         keyData.bytes,           // password
                         keyData.length,          // passwordLength
                         salt.bytes,              // salt
                         salt.length,             // saltLen
                         kCCPRFHmacAlgSHA1,       // PRF
                         rounds,                  // rounds
                         derivedKey.mutableBytes, // derivedKey
                         dkLen*8);
 return derivedKey;

I am getting a different output. I am doing anything wrong?.please help me to find out.

解决方案

One problem is that the Java code used CBC mode, the iOS code used ECB mode.

Next, from the referenced project:
//result= yHbhApwTpQ2ZhE97AKF/g==
is invalid Base64, it does not contain a multiple of 4 bytes.

With these options: CBC, PKCS#7 padding

inputs:
   data in: "hello" which will be null padded to the block length of 16-bytes
   key:
      base64: VQQhu+dUdqXGoE7RZL2JWg==
      hex: 550421bbe75476a5c6a04ed164bd895a
   iv:
      base64: VQQhu+dUdqXGoE7RZL2JWg==
      hex: 550421bbe75476a5c6a04ed164bd895a
encrypted output:
   hex: ff21db840a704e943666113dec0285fe
   base64: /yHbhApwTpQ2ZhE97AKF/g==

This is the test code:

NSString *base64Key  = @"VQQhu+dUdqXGoE7RZL2JWg==";
NSString *dataString = @"hello";

NSData *key  = [[NSData alloc] initWithBase64EncodedString:base64Key  options:0];
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];

NSLog(@"key:  %@", key);
NSLog(@"data: %@", data);

NSData *encryptedData = [TestClass crypt:data
                                 iv:key
                                key:key
                            context:kCCEncrypt];

NSLog(@"encryptedData: %@", encryptedData);
NSString *encryptedBase64Data = [encryptedData base64EncodedStringWithOptions:0];
NSLog(@"encryptedBase64Data: %@", encryptedBase64Data);

This is the encryption method (in the class TestClass):

+ (NSData *)crypt:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES128,
                       kCCOptionPKCS7Padding,
                       symmetricKey.bytes,
                       kCCKeySizeAES128,
                       iv.bytes,
                       dataIn.bytes,
                       dataIn.length,
                       dataOut.mutableBytes,
                       dataOut.length,
                       &cryptBytes);

    if (ccStatus != kCCSuccess) {
        NSLog(@"CCCrypt status: %d", ccStatus);
    }

    dataOut.length = cryptBytes;

    return dataOut;
}

Note: I keep separate the encryption and data conversions. Conflating them just makes testing more complicated.

If you use an on-line encryption implementation the padding will probably not be PKCS#7 because mcrypt does not support it, instead it does non-standard null padding. Since the pad bytes are just the count of pad bytes the padding can be simulated in the input. Here is an example using AES – Symmetric Ciphers Online

Note that "hello" PKCS#7 padded to a block size of 16 bytes adds 11 bytes of the uint8 value 11 or 0x0B: 68656c6c6f0B0B0B0B0B0B0B0B0B0B0B.

Finally the question remains why the Java code does not produce this result?

这篇关于在IOS中实现AES256加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 20:51