AES/CBC/PKCS5Padding加密iOS

4

我在Android中使用了AES算法进行加密。 以下是我们用于加密的代码。

String seed = "somekey";
        Key key = null;
        // 128 bit key
        byte[] byteKey = seed.substring(0, 16).getBytes("UTF-8");
        key = new SecretKeySpec(byteKey, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(
                new byte[16]));
        byte[] encValue = cipher.doFinal(pValue.getBytes());
        encryptedText = new BASE64Encoder().encode(encValue);

请问有人能提供上述逻辑的IOS版本吗?

提前感谢。


提供有关SecretKeySpecCipher的信息,例如文档链接。目前信息不足。如果您在每个语句后提供示例数据和十六进制转储,则会更有帮助。 - zaph
3个回答

2

它在Android上的使用方式如下:

#define FBENCRYPT_KEY_SIZE      kCCKeySizeAES128

替代方案:

#define FBENCRYPT_KEY_SIZE      kCCKeySizeAES256

1
由于AES块大小为16字节,因此需要使用PKCS#7填充。一些早期的AES库实现者错误地指定了PKCS#5填充。 只有对于块大小最多为8字节才指定PKCS#5填充,而对于块大小最多为255字节,指定了PKCS#7填充。请参见维基百科:填充。换句话说,PKCS#7填充可以代替PKCS#5填充。

嗨Zaph,我发现你在这里发布了一个非常好的代码链接:https://stackoverflow.com/questions/46221794/generate-initialization-vector-in-objective-c。请问如何在这里生成随机“key”? - User1075

1
您可以使用以下代码片段作为起点:
+ (NSData*)encryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv;
{
    NSData* result = nil;

    // setup key
    unsigned char cKey[FBENCRYPT_KEY_SIZE];
    bzero(cKey, sizeof(cKey));
    [key getBytes:cKey length:FBENCRYPT_KEY_SIZE];

    // setup iv
    char cIv[FBENCRYPT_BLOCK_SIZE];
    bzero(cIv, FBENCRYPT_BLOCK_SIZE);
    if (iv) {
        [iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE];
    }

    // setup output buffer
    size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
    void *buffer = malloc(bufferSize);

    // do encrypt
    size_t encryptedSize = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          FBENCRYPT_ALGORITHM,
                                          kCCOptionPKCS7Padding,
                                          cKey,
                                          FBENCRYPT_KEY_SIZE,
                                          cIv,
                                          [data bytes],
                                          [data length],
                                          buffer,
                                          bufferSize,
                                          &encryptedSize);
    if (cryptStatus == kCCSuccess) {
        result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
    } else {
        free(buffer);
        NSLog(@"[ERROR] failed to encrypt|CCCryptoStatus: %d", cryptStatus);
    }

    return result;
}

+ (NSData*)decryptData:(NSData*)data key:(NSData*)key iv:(NSData*)iv;
{
    NSData* result = nil;

    // setup key
    unsigned char cKey[FBENCRYPT_KEY_SIZE];
    bzero(cKey, sizeof(cKey));
    [key getBytes:cKey length:FBENCRYPT_KEY_SIZE];

    // setup iv
    char cIv[FBENCRYPT_BLOCK_SIZE];
    bzero(cIv, FBENCRYPT_BLOCK_SIZE);
    if (iv) {
        [iv getBytes:cIv length:FBENCRYPT_BLOCK_SIZE];
    }

    // setup output buffer
    size_t bufferSize = [data length] + FBENCRYPT_BLOCK_SIZE;
    void *buffer = malloc(bufferSize);

    // do decrypt
    size_t decryptedSize = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          FBENCRYPT_ALGORITHM,
                                          kCCOptionPKCS7Padding,
                                          cKey,
                                          FBENCRYPT_KEY_SIZE,
                                          cIv,
                                          [data bytes],
                                          [data length],
                                          buffer,
                                          bufferSize,
                                          &decryptedSize);

    if (cryptStatus == kCCSuccess) {
        result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
    } else {
        free(buffer);
        NSLog(@"[ERROR] failed to decrypt| CCCryptoStatus: %d", cryptStatus);
    }

    return result;
}

常量
#define FBENCRYPT_ALGORITHM     kCCAlgorithmAES128
#define FBENCRYPT_BLOCK_SIZE    kCCBlockSizeAES128
#define FBENCRYPT_KEY_SIZE      kCCKeySizeAES256

更多信息请参见FBEncryptor

希望这可以帮到你。


1
你好Doro,感谢您宝贵的建议。CommonCrypto iOS不支持PKCS5Padding。iOS仅支持PKCS7Padding。是否有第三方工具可用于支持PKCS5Padding? - Jagadeesh K
@jagadeesh 他们指的是相同的填充。 - Artjom B.
你好Artjom,我需要一个iOS的算法(AES/CBC/PKCS5Padding)。限制条件是iOS仅支持PKCS7Padding。 - Jagadeesh K
正如我所说,它们是相同的:http://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding - Artjom B.
@Doro OP正在使用128位密钥。此外,该密钥是通过SecretKeySpec方法扩展的。还有一个由IvParameterSpec创建的iv,可以预先添加到加密数据中。答案中没有处理这些内容。AES块大小为16字节,但答案将8添加到bufferSize进行填充是不正确的,最好使用常量:kCCBlockSizeAES128 - zaph
@Doro 为什么要定义 FBENCRYPT_* 常量而不直接使用 Common Crypto 常量?这样做只会增加混淆和代码。仍然没有改变:OP 指定了一个 128 位的密钥,而答案使用了 256 位。种子通过 SecretKeySpec 方法扩展到密钥中。还有一个 iv 由 IvParameterSpec 创建,可以预先添加到加密数据中。答案中没有处理任何这些内容。加密和解密几乎完全相同,这会创建需要一起管理的重复代码,这是非常糟糕的实践。 - zaph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接