在iOS上生成的RSA密钥不能在Android上运行

时间:2015-10-20 20:36:03

标签: android ios encryption rsa x509

我使用以下代码在iOS上生成密钥

let parameters: [String: AnyObject] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: 1024]
        var publicKeyPtr, privateKeyPtr: SecKey?
        let result = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
        print(result)

        let publicKey = publicKeyPtr!
        let privateKey = privateKeyPtr!

let encodedPublicKey = convertSecKeyToBase64(publicKey)!

func convertSecKeyToBase64(inputKey: SecKey) ->String? {
        // First Temp add to keychain
        let tempTag = "de.a-bundle-id.temp"
        let addParameters :[String:AnyObject] = [
            String(kSecClass): kSecClassKey,
            String(kSecAttrApplicationTag): tempTag,
            String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
            String(kSecValueRef): inputKey,
            String(kSecReturnData):kCFBooleanTrue
        ]

        var keyPtr: AnyObject?
        let result = SecItemAdd(addParameters, &keyPtr)
        switch result {
        case noErr:
            let data = keyPtr! as! NSData

            // Remove from Keychain again:
            SecItemDelete(addParameters)
            let encodingParameter = NSDataBase64EncodingOptions(rawValue: 0)
            return data.base64EncodedStringWithOptions(encodingParameter)

        default:
            print("Error: \(result)")
            return nil
        }
    }

编码的公钥如下所示

MIGJAoGBAJZhrrBPuKvq8RuVPeg02D2iPahmVS9oomaqxITNcifBO6hhYomp4mlbubSWMYiHPbpeX7+gmG41B7E5BSJ7nHq7KZ9OMqiAekY5JhRmJlAhmKsBmjrSNbt0wqNXl3dxjj/sc1qauQBXY8X5fhEmatWDwvfb7nq/8yloPc5iAUalAgMBAAE=

在Android上解密时,我收到错误消息  java.security.spec.InvalidKeySpecException:java.lang.RuntimeException:error:0D0680A8:asn1编码例程:ASN1_CHECK_TLEN:标记错误

显然,在iOS上生成的密钥类型不是Android代码所需的类型,我如何让iOS使用X509类型?以下是Android代码

public static String encrypt(String text, Context c, String pub) {
        try {
            byte[] pubKey = Base64.decode(pub, 0);

            KeyFactory factory = KeyFactory.getInstance("RSA");
            EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey);
            PublicKey key = factory.generatePublic(keySpec);

            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");

            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] bytes = text.getBytes("UTF-8");

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            for (int i = 0; i < (bytes.length / 128 + 1); i++) {
                int start = i * 128;
                int blockLength;
                if (i == bytes.length / 128)
                    blockLength = bytes.length - i * 128;
                else
                    blockLength = 128;
                if (blockLength > 0) {
                    byte[] encrypted = cipher
                            .doFinal(bytes, start, blockLength);
                    baos.write(encrypted);
                }

            }

            byte[] encrypted = baos.toByteArray();
            return Base64.encodeToString(encrypted, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2 个答案:

答案 0 :(得分:0)

我引用Berin在blog

中写的内容
  

首先,当您从iPhone钥匙串导出密钥时,它会以缩减格式导出 - 只需公钥和指数,而不需要在完全编码的公钥中使用任何其他ASN.1内容。 java加密函数通常需要一个完全编码的密钥(OID和all)。

总之,SecKeyGeneratePair生成的公钥不是完整格式。为了使Android能够使用它,需要手动扩展。可以在该博客中找到更多内容。

答案 1 :(得分:0)

将CryptoExportImportManager.swift文件从下面拖放到您的项目中。这将使您能够以PEM和DER格式导出在iOS上生成的密钥,这些密钥可以传递给Android和其他平台。自述文件中的信息将详细说明。

https://github.com/DigitalLeaves/CryptoExportImportManager