首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用iOS加密,用Java解密

用iOS加密,用Java解密
EN

Stack Overflow用户
提问于 2014-09-30 04:51:57
回答 2查看 9.7K关注 0票数 20

我有一个从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

  • iOS:

  • iOS: PKCS1,Java:org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.)

  • iOS:

  • iOS: PKCS1,Java: RSA PKCS1,Java: RSA

  • iOS: PKCS1,Java: RSA/None/PKCS1Padding.pkcs1Padding.pkCS1Padding.pkCS1Padding.pkcs1Padding.pkcs1Padding.pkCS1Padding.pkCS1Padding.pkcs1Padding.pkCS1Padding.pk

我还尝试使用内部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个字节。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26108672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档