3

我正在尝试在 iOS 上使用带有 kSecPaddingPKCS1 的 RSA (SecKeyEncrypt) 加密 AES 密钥,然后使用 RSA 算法的标准 java 提供程序 (javax.crypto) 解密密钥。我成功接收到由 java 应用程序生成的公钥,将其存储在 iOS 钥匙串中并使用它来加密 aes 密钥,但是在 java 应用程序上接收时 - 我得到了众所周知的异常 javax.crypto.BadPaddingException: Data must start与零。当我禁用填充时,相同的代码有效(有时有效)。那么在 iOS 和 Java patform 上使用的 padding 有什么区别呢?有人可以给我答案 - 我在这个问题上挣扎了太久。失去了耐心。

源代码。1) 生成对称密钥,2) 使用我的 java 应用程序中的 rsa 公钥包装它。(Tke 公钥从模数和指数创建,由 java 应用程序发送到客户端) 3)准备 NSData:使用加密密钥初始化,附加 aes 加密数据,发送到 java 应用程序。然后 java 应用程序获取前 128 个字节(加密的 aes 密钥)并尝试对其进行解密,并在此处引发异常。

 [tools generateSymmetricKey];
NSData* encryptedSymetricKey = [tools wrapSymmetricKey:[tools getSymmetricKeyBytes] keyRef:[tools getPeerPublicKeyRef]];
int option = kCCOptionPKCS7Padding;
NSData* aesEncr = [tools doCipher:data key:[tools getSymmetricKeyBytes] context:kCCEncrypt  padding:(CCOptions *)&option];
NSMutableData * result = [[NSMutableData alloc] initWithData:encryptedSymetricKey];
[result appendData:aesEncr];

以及从 CryptoExercise 借来的方法,它应该适用于我 imo:

- (NSData *)wrapSymmetricKey:(NSData *)symmetricKey keyRef:(SecKeyRef)publicKey {
OSStatus sanityCheck = noErr;
size_t cipherBufferSize = 0;
size_t keyBufferSize = 0;

LOGGING_FACILITY( symmetricKey != nil, @"Symmetric key parameter is nil." );
LOGGING_FACILITY( publicKey != nil, @"Key parameter is nil." );

NSData * cipher = nil;
uint8_t * cipherBuffer = NULL;

// Calculate the buffer sizes.
cipherBufferSize = SecKeyGetBlockSize(publicKey);
keyBufferSize = [symmetricKey length];

if (kTypeOfWrapPadding == kSecPaddingNone) {
    LOGGING_FACILITY( keyBufferSize <= cipherBufferSize, @"Nonce integer is too large and falls outside multiplicative group." );
} else {
    LOGGING_FACILITY( keyBufferSize <= (cipherBufferSize - 11), @"Nonce integer is too large and falls outside multiplicative group." );
}

// Allocate some buffer space. I don't trust calloc.
cipherBuffer = malloc( cipherBufferSize * sizeof(uint8_t) );
memset((void *)cipherBuffer, 0x0, cipherBufferSize);

// Encrypt using the public key.
sanityCheck = SecKeyEncrypt(    publicKey,
                                kSecPaddingPKCS1,
                                (const uint8_t *)[symmetricKey bytes],
                                keyBufferSize,
                                cipherBuffer,
                                &cipherBufferSize
                            );


LOGGING_FACILITY1( sanityCheck == noErr, @"Error encrypting, OSStatus == %d.", sanityCheck );

// Build up cipher text blob.
cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];

if (cipherBuffer) free(cipherBuffer);

return cipher;

}

还有一件事。在 java 方面,我使用的是 RSA/ECB/PKCS1Padding 密码实例。

我如何传输公钥:java 生成的公钥解耦为模数和指数,然后两个值都转换为原始字节数组,并发送,然后在 ios 客户端复制它们,转换为 ios 密钥环兼容格式并插入到钥匙圈。公钥正确传输,我比较了两边的模数和公共指数,它们匹配。公钥已成功导入 ios 上的密钥环(这是通过 BasicEncodingRules BER 类别完成的)。我认为 PKCS1padding 填充支持一定有问题 - 它在两个平台上都必须不同(可能与填充相关的计算需要在 ios 上添加一些额外的东西)。

4

0 回答 0