5

我有一个应用程序需要使用 AES/CBC/无填充对一些数据进行编码。该应用程序也移植到android上。那里的编码是这样完成的:

byte[] encodedKey = getKey();
    SecretKeySpec skeySpec = new SecretKeySpec(encodedKey, "AES");
    AlgorithmParameterSpec paramSpec = new IvParameterSpec(initializationVector);

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, paramSpec);

    int blockSize = cipher.getBlockSize();
    int diffSize = decrypted.length % blockSize;
    System.out.println("Cipher size: " + blockSize);
    System.out.println("Current size: " + decrypted.length);
    if (diffSize != 0) {
      diffSize = blockSize - diffSize;
      byte[] oldDecrypted = decrypted;
      decrypted = new byte[decrypted.length + diffSize];
      System.arraycopy(oldDecrypted, 0, decrypted, 0, oldDecrypted.length);
      for (int i = 0; i < diffSize; i++) {
        decrypted[i + oldDecrypted.length] = " ".getBytes()[0];
      }
      System.out.println("New size: " + decrypted.length);

    }
    return cipher.doFinal(decrypted);

初始化向量看起来像这样:

private byte[] initializationVector = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

在iOS上我有这样的加密:

- (NSData *)AES128EncryptWithKey:(NSString *)key 
{
    // 'key' should be 16 bytes for AES128, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128+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, 
                                          0x0000,
                                          keyPtr, 
                                          kCCKeySizeAES128,
                                          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;
}

上述方法是 NSData 类别的一部分。该方法是这样调用的:

NSData *data = [@"4915200456727" dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipher  = [data AES128EncryptWithKey:@"@x#zddXekZerBBw6"];
    NSString *ecriptedString = [NSString stringWithFormat:@"%.*s", [cipher length], [cipher bytes]];

我遇到的问题是我在 iOS 和 android 上没有收到相同的加密数据。在 iOS 上,加密数据的长度为 0 字节。

您能否就如何使用带有 CBC 且没有填充的 AES128 加密字符串以及可能的示例给出任何指示?

谢谢

4

1 回答 1

8

我找到了解决我的问题的方法。为了使加密在没有填充的情况下工作,我必须添加 0x0000 而不是处理的 kCCOptionPKCS7Padding 或 kCCOptionECBMode 。

此外,如果需要编码的数据的长度不是 kCCKeySizeAES128 ( 16 ) 的倍数,则必须调整保存数据的向量的大小,使其具有 kCCKeySizeAES128 的长度倍数,并且空值填充一些东西。我添加了空格。

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

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

    int dataLength = [self length];
    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
    int newSize = 0;

    if(diff > 0)
    {
        newSize = dataLength + diff;
    }

    char dataPtr[newSize];
    memcpy(dataPtr, [self bytes], [self length]);
    for(int i = 0; i < diff; i++)
    {
        dataPtr[i + dataLength] = 0x20;
    }

    size_t bufferSize = newSize + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          0x0000, //No padding
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          NULL,
                                          dataPtr,
                                          sizeof(dataPtr),
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);

    if(cryptStatus == kCCSuccess)
    {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    return nil;
}
于 2012-06-06T09:21:29.640 回答