【问题标题】:RSA keys generated on iOS won't work on Android在 iOS 上生成的 RSA 密钥在 Android 上不起作用
【发布时间】:2016-01-19 16:26:43
【问题描述】:

我正在使用以下代码在 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 encoding routines:ASN1_CHECK_TLEN:wrong tag

显然在 iOS 上生成的密钥类型不是 Android 代码正在寻找的类型,我怎样才能让 iOS 使用 X509 类型?下面是安卓代码

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;
    }

【问题讨论】:

    标签: android ios encryption rsa x509


    【解决方案1】:

    将 CryptoExportImportManager.swift 文件从下方拖放到您的项目中。这将使您能够以 PEM 和 DER 格式导出在 iOS 上生成的密钥,这些密钥可以传递到 Android 和其他平台。 README 中的信息将解释更多。

    https://github.com/DigitalLeaves/CryptoExportImportManager

    【讨论】:

      【解决方案2】:

      我引用了 Berin 在他的 blog 中写的内容

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

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

      【讨论】:

      • 这太棒了!这让我很沮丧,为什么每次我用谷歌搜索快速生成 RSA 总是在在线 RSA 加密和解密中失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-25
      • 1970-01-01
      • 2021-05-08
      • 2015-04-02
      • 2016-06-12
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多