Сбой открытого ключа шифрования RSA для сервера Java - PullRequest
2 голосов
/ 17 июня 2019

Я пытаюсь создать открытый ключ base64 из RSA Private key, используя Security framework.Вот фрагмент кода.

let tag = "com.example.keys.mykey"
public extension SecKey {
    static func generateBase64Encoded2048BitRSAKey() throws -> (private: String, public: String) {
        let type = kSecAttrKeyTypeRSA
        let attributes: [String: Any] =
            [kSecAttrKeyType as String: type,
             kSecAttrKeySizeInBits as String: 2048
        ]

        var error: Unmanaged<CFError>?
        guard let key = SecKeyCreateRandomKey(attributes as CFDictionary, &error),
            let data = SecKeyCopyExternalRepresentation(key, &error) as Data?,
            let publicKey = SecKeyCopyPublicKey(key),
            let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else {
                throw error!.takeRetainedValue() as Error
        }
        return (private: data.base64EncodedString(), public: publicKeyData.base64EncodedString())
    }
}

do {
    let (pvtKey, pubKey) = try SecKey.generateBase64Encoded2048BitRSAKey()
    print(pubKey)
} catch let error {
    print(error)
}

Это вывод

MIIBCgKCAQEA1ZafTYboquQbCTZMEb1IqHKIr8wiDjdn6e0toRajZCQo9W5zuTlEuctrjJJQ08HcOuK3BPFRaFTUP1RBFvnba/T2S1Mc6WVX81b0DmKS8aPJ83TvvQlH3bZjVqFzndXJHJatcXRkZKlbidNQYxV9OYFCRLwgR5PBoJ1P5tp8f8735vIADOBL/93nFywODSjAWLXcyG5tUyRlRGX7eDodL7jqVOFxVMB7K9UOJehPuJQiheykyPSbBSLE6raZbpCHlranTLdihWYFs2tYbxzNrVbXzgKIxDDjrhDLVFvo3beudKQcLQkSO+m2LJIDT91zAnxVQ075AIn80ZHh5kdyQQIDAQAB

Но этот открытый ключ не принимается нашим сервером Java.Это исключение для того же.

Вот фрагмент кода Java

public static void main(String[] args) {
        String pubKey = "MIIBCgKCAQEA1ZafTYboquQbCTZMEb1IqHKIr8wiDjdn6e0toRajZCQo9W5zuTlEuctrjJJQ08HcOuK3BPFRaFTUP1RBFvnba/T2S1Mc6WVX81b0DmKS8aPJ83TvvQlH3bZjVqFzndXJHJatcXRkZKlbidNQYxV9OYFCRLwgR5PBoJ1P5tp8f8735vIADOBL/93nFywODSjAWLXcyG5tUyRlRGX7eDodL7jqVOFxVMB7K9UOJehPuJQiheykyPSbBSLE6raZbpCHlranTLdihWYFs2tYbxzNrVbXzgKIxDDjrhDLVFvo3beudKQcLQkSO+m2LJIDT91zAnxVQ075AIn80ZHh5kdyQQIDAQAB";
        PublicKey key = getPublic(pubKey);
    }

    public static PublicKey getPublic(String key)  {
        PublicKey pbKey = null; 
        try {
            byte[] keyBytes = Base64.getDecoder().decode(key);
            System.out.println(keyBytes.length);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory factory = KeyFactory.getInstance("RSA");
            pbKey = factory.generatePublic(spec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pbKey;
    }

Вот исключение

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
    at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
    at Main.getPublic(Main.java:40)
    at Main.main(Main.java:28)

Но веб-сайт PEM-анализатора онлайн - https://8gwifi.org/PemParserFunctions.jsp принимает этот открытый ключ, который использует библиотеку bouncycastle в фоновом режиме для проверки этого закодированного в base64 открытого ключа.

enter image description here

1 Ответ

0 голосов
/ 19 июня 2019

Спасибо, ребята.Из-за некоторых проблем с библиотекой bouncycastle мы не использовали ее в бэкэнд-сервисе.Поэтому в iOS мы включаем заголовок ASN1.

struct ASN1 {
    let type: UInt8
    let length: Int
    let data: Data

    init?(type: UInt8, arbitraryData data: Data) {
        guard data.count > 4 else {
            return nil
        }

        var result = data

        let byteArray = [UInt8](result)

        for (_, v) in byteArray.enumerated() {
            if v == type { // ASN1 SEQUENCE Type
                break
            }
            result = Data(result.dropFirst())
        }
        guard result.count > 4 else {
            return nil
        }
        guard
            let first = result.advanced(by: 0).first, // advanced start from 7.0
            let second = result.advanced(by: 1).first,
            let third = result.advanced(by: 2).first,
            let fourth = result.advanced(by: 3).first
            else {
                return nil
        }

        var length = 0
        switch second {
        case 0x82:
            length = ((Int(third) << 8) | Int(fourth)) + 4
            break
        case 0x81:
            length = Int(third) + 3
            break
        default:
            length = Int(second) + 2
            break
        }

        guard result.startIndex + length <= result.endIndex else { // startIndex, endIndex start from 7.0
            return nil
        }
        result = result[result.startIndex..<result.startIndex + length]
        self.data = result
        self.length = length
        self.type = first
    }

    var last: ASN1? {
        get {
            var result: Data?
            var dataToFetch = self.data
            while let fetched = ASN1(type: self.type, arbitraryData: dataToFetch) {

                if let range = data.range(of: fetched.data) {
                    if range.upperBound == data.count {
                        result = fetched.data
                        dataToFetch = Data(fetched.data.dropFirst())
                    } else {
                        dataToFetch = Data(data.dropFirst(range.upperBound))
                    }
                } else {
                    break
                }
            }

            return ASN1(type: type, arbitraryData: result!)
        }
    }

    static func wrap(type: UInt8, followingData: Data) -> Data {
        var adjustedFollowingData = followingData
        if type == 0x03 {
            adjustedFollowingData = Data([0]) + followingData // add prefix 0
        }
        let lengthOfAdjustedFollowingData = adjustedFollowingData.count
        let first: UInt8 = type
        var bytes = [UInt8]()
        if lengthOfAdjustedFollowingData <= 0x80 {
            let second: UInt8 = UInt8(lengthOfAdjustedFollowingData)
            bytes = [first, second]
        } else if lengthOfAdjustedFollowingData > 0x80 && lengthOfAdjustedFollowingData <= 0xFF {
            let second: UInt8 = UInt8(0x81)
            let third: UInt8 = UInt8(lengthOfAdjustedFollowingData)
            bytes = [first, second, third]
        } else {
            let second: UInt8 = UInt8(0x82)
            let third: UInt8 = UInt8(lengthOfAdjustedFollowingData >> 8)
            let fourth: UInt8 = UInt8(lengthOfAdjustedFollowingData & 0xFF)
            bytes = [first, second, third, fourth]
        }
        return Data(bytes) + adjustedFollowingData
    }

    static func rsaOID() -> Data {
        var bytes = [UInt8]()
        bytes = [0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00]
        return Data(bytes)
    }
}

Затем вызывали его во время генерации открытого ключа RSA в swift.

class func RSAPublicKeyBitsFromKey(_ secKey:SecKey) -> Data? {

    var queryPublicKey:[String:AnyObject] = [:]
    queryPublicKey[kSecClass as String] = kSecClassKey as NSString
    queryPublicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA as NSString

    if let publicKeyData = SwiftCrypto.publicKeyInData(queryPublicKey, secKey: secKey) {
        let bitstringSequence = ASN1.wrap(type: 0x03, followingData: publicKeyData)
        let oidData = ASN1.rsaOID()
        let oidSequence = ASN1.wrap(type: 0x30, followingData: oidData)
        let X509Sequence = ASN1.wrap(type: 0x30, followingData: oidSequence + bitstringSequence)
        return X509Sequence
    }
    return nil
}

Итак, таким образом, у меня былоисправил эту проблему.

...