我有一个从Java服务器发送的公钥。在我解码和剥离base64报头之前,编码的字符串是匹配的。我使用SecItemAdd
将公钥存储在密钥链中。
因此,我尝试使用Java中的公钥加密数据,并使用私钥解密数据。我在Java端使用SecKeyEncrypt
,在Java端使用Cipher
。
我加密的是对称的AES密钥,它加密我的实际数据,所以密钥长度是16字节。当简单地对密钥进行base64编码时,一切都正常,所以我知道这个出了问题。
下面是我的iOS调用的一个示例:
OSStatus sanityCheck = SecKeyEncrypt(publicKey,
kSecPaddingPKCS1,
(const uint8_t *) [incomingData bytes],
keyBufferSize,
cipherBuffer,
&cipherBufferSize
);
下面是我的Java调用的一个示例:
public static byte[] decryptMessage (byte[] message, PrivateKey privateKey, String algorithm) {
if (message == null || privateKey == null) {
return null;
}
Cipher cipher = createCipher(Cipher.DECRYPT_MODE, privateKey, algorithm, false);
if (cipher == null) {
return null;
}
try {
return cipher.doFinal(message);
}
catch (IllegalBlockSizeException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
catch (BadPaddingException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
}
private static Cipher createCipher (int mode, Key encryptionKey, String algorithm, boolean useBouncyCastle) {
Cipher cipher;
try {
if (useBouncyCastle) {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher = Cipher.getInstance(algorithm, "BC");
}
else {
cipher = Cipher.getInstance(algorithm);
}
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
catch (NoSuchPaddingException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
catch (NoSuchProviderException e) {
e.printStackTrace();
return null;
}
try {
cipher.init(mode, encryptionKey);
}
catch (InvalidKeyException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
return cipher;
}
我尝试了这么多组合,但都不起作用。
RSA/ECB/PKCS1Padding
org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
)
我还尝试使用内部Java提供程序和BouncyCastle提供程序。每次都会抛出javax.crypto.BadPaddingException
,但每种组合的消息都不同。一些显示Data must start with zero
,而另一些则显示Message is larger than modulus
。
iOS: PKCS1, Java: RSA
没有抛出异常,但是得到的解密的byte[]
数组的长度应该是16,但是它的长度是256,这意味着填充没有被正确地剥离。
有人能帮帮忙吗?
*编辑*
当我做更多的测试时,我遇到了这个页面(http://javadoc.iaik.tugraz.at/iaik_jce/current/iaik/pkcs/pkcs1/RSACipher.html),它基本上告诉我RSA == RSA/None/PKCS1Padding
。解密工作在没有例外的意义上,但我仍然得到一个解密的密钥,它的byte[]长度是256而不是16。
另一个有趣的地方。看起来,如果Java服务器拥有从iOS设备生成的公钥并使用Cipher.getInstance("RSA")
加密,那么手机就能够使用RSAPKCS1正确地解码消息。
*编辑2个*
我已经阅读了这些教程,并在iOS端再次查看了我的代码:
据我所知,我的代码一切都是正确的。一个重要的区别是我保存密钥的方式,所以我尝试以另一种方式保存它:
OSStatus error = noErr;
CFTypeRef persistPeer = NULL;
NSMutableDictionary * keyAttr = [[NSMutableDictionary alloc] init];
keyAttr[(__bridge id) kSecClass] = (__bridge id) kSecClassKey;
keyAttr[(__bridge id) kSecAttrKeyType] = (__bridge id) kSecAttrKeyTypeRSA;
keyAttr[(__bridge id) kSecAttrApplicationTag] = [secKeyWrapper getKeyTag:serverPublicKeyTag];
keyAttr[(__bridge id) kSecValueData] = strippedServerPublicKey;
keyAttr[(__bridge id) kSecReturnPersistentRef] = @YES;
error = SecItemAdd((__bridge CFDictionaryRef) keyAttr, (CFTypeRef *)&persistPeer);
if (persistPeer == nil || ( error != noErr && error != errSecDuplicateItem)) {
NSLog(@"Problem adding public key to keychain");
return;
}
CFRelease(persistPeer);
保存成功,但最终结果是相同的:解密的AES密钥的长度仍然是256个字节,而不是16个字节。
https://stackoverflow.com/questions/26108672
复制相似问题