首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何解析x509证书并在Swift中提取其密钥签名?

如何解析x509证书并在Swift中提取其密钥签名?
EN

Stack Overflow用户
提问于 2022-08-23 07:29:01
回答 1查看 333关注 0票数 4

我正在尝试生成一个RSA对密钥,然后将一个X.509证书添加到公钥的头部。为此,我使用了库SwiftyRSA

问题是,当我将X.509证书添加到报头时,我无法解析公钥。当我在之后打印公钥时,它仍然显示与没有证书的相同。

但是,当我打印字节时,它会显示不同的字节,如果没有证书,它将显示270个字节,而证书则显示294字节。这意味着它正在添加证书,但它没有使用证书解析它。

在深入阅读了SwiftyRSA库之后,它说:

警告:存储(使用SwiftyRSA的方法)或创建PublicKey实例将自动从键中删除标头。有关更多信息,请参见上面的引擎盖下面。

如果值得一提的话,甚至还有那个箱子还在那里。

我仍在寻找解决办法,但找不到任何解决办法。我试图实现的代码:

代码语言:javascript
复制
    if let password = passwordTextField.text {

        //Generate RSA
        guard let keyPair = try? SwiftyRSA.generateRSAKeyPair(sizeInBits: 2048),
              let privateKeyPem = try? keyPair.privateKey.pemString(),
              let publicKeyPem = try? keyPair.publicKey.pemString()
        else {
            return
        }
        
        /// Generate Certificate in format X.509 from Public Key
        let publicKey = try! PublicKey(data: keyPair.publicKey.data())
        let publicKeyData = try! keyPair.publicKey.data()
        let publicKey_with_X509_header = try! SwiftyRSA.prependX509KeyHeader(keyData: publicKeyData)
        
        let publicKey509 = try! PublicKey(data: publicKey_with_X509_header)
        
        print(try! publicKey.pemString()) // Without Certificate
        print(try! publicKey509.pemString()) // With Certificate
        // These two print results are completely the same, but it should be different.

        // Encrypt private key
        let salt = String.random(length: 32)
        let aesKey = Array(String((password + salt).prefix(32)).utf8)
        let iv = [UInt8](String(salt.prefix(16)).utf8)
        guard let aes = try? AES(key: aesKey, blockMode: CBC(iv: iv), padding: .pkcs7),
              let inputData = privateKeyPem.data(using: .utf8),
              let encryptedBytes = try? aes.encrypt(inputData.bytes)
        else {
            return
        }

        let encryptedData = NSData(bytes: encryptedBytes, length: encryptedBytes.count)
        let base64String = encryptedData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))

        // Print keys and salt
        print(try! publicKey509.pemString())
        print(base64String)
        print(salt)
        
    }

如何使用x509证书解析公钥?如有任何贡献,我将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-10 22:27:39

如前所述,您将无法使用x509创建SwiftyRSA证书。实际上,您可以使用安全性框架来完成这一任务。

首先,您需要创建Data的扩展,它将用于将证书添加到公钥。

代码语言:javascript
复制
extension Data {
    public func dataByPrependingX509Header() -> Data { 
        let result = NSMutableData()
        let encodingLength: Int = (self.count + 1).encodedOctets().count
        let OID: [CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00]
        var builder: [CUnsignedChar] = []
        
        // ASN.1 SEQUENCE
        builder.append(0x30)
        
        // Overall size, made of OID + bitstring encoding + actual key
        
        let size = OID.count + 2 + encodingLength + self.count
        let encodedSize = size.encodedOctets()
        builder.append(contentsOf: encodedSize)
        result.append(builder, length: builder.count)
        result.append(OID, length: OID.count)
        builder.removeAll(keepingCapacity: false)
        builder.append(0x03)
        builder.append(contentsOf: (self.count + 1).encodedOctets())
        builder.append(0x00)
        result.append(builder, length: builder.count)
        
        // Actual key bytes
        result.append(self)
        return result as Data
        
    }
    
}

然后,确保您的import Security并将您的代码更改为:

代码语言:javascript
复制
    // Generate keys
    if let password = passwordTextField.text {
        //Generate RSA
        let attributes: [String: Any] = [
            String(kSecAttrKeyType):            kSecAttrKeyTypeRSA,
            String(kSecAttrKeySizeInBits):      4096, // you can change the size to 2048, but 4096 has higher security.
            String(kSecPrivateKeyAttrs): [
                String(kSecAttrIsPermanent):    true,
                String(kSecAttrApplicationTag): "com.example.keys.mykey"]
        ]
        var error: Unmanaged<CFError>?
        
        // Private Key
        guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
            fatalError("Error: \(error.debugDescription)")
        }
        
        let privateKeyData = SecKeyCopyExternalRepresentation(privateKey, &error)
        let privData = privateKeyData as Data?
        let privateKeyString = privData!.base64EncodedString()
        print("Private Key")
        print(privateKeyString)

        // You'll probably need to structure Private and public key to go in new line every time after 76 character
        let structuredPrivateKeyString = privateKeyString.inserting(separator: "\n", every: 76)
        let privateKeyFinal = "-----BEGIN RSA PRIVATE KEY-----\n" + structuredPrivateKeyString + "\n\n-----END RSA PRIVATE KEY-----" 
        print(privateKeyFinal)
        
        // Public Key
        let publicKey = SecKeyCopyPublicKey(privateKey) // generate public key from private key
        let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, &error)
        let pubData = publicKeyData as Data? // We need to turn it into data so we can add the certificate or print it as string
        print("Public Key")
        print(pubData!.base64EncodedString())
        
        // Add x509 certificate to public key
        let publicKeyX509 = SecKeyCopyPublicKey(privateKey)
        let publicKeyDataX509 = SecKeyCopyExternalRepresentation(publicKeyX509!, &error)
        let pubData1 = publicKeyDataX509 as Data?
        let x509Data = pubData1!.dataByPrependingX509Header() // Here we add the certificate (Function that we created previosly in Data extension).
        var publicKeyX509String = x509Data.base64EncodedString()
        print("Public Key x509")
        print(publicKeyX509String)
        
        let structuredPublicKeyX509String = publicKeyX509String.inserting(separator: "\n", every: 76)
        
        let publicKeyFinal = "-----BEGIN RSA PUBLIC KEY-----\n\(structuredPublicKeyX509String)\n\n-----END RSA PUBLIC KEY-----"
        print("Public Key for the API")
        print(publicKeyFinal)
        
        // Encrypt private key
        let salt = String.random(length: 32)
        let aesKey = Array(String((password + salt).prefix(32)).utf8)
        let iv = [UInt8](String(salt.prefix(16)).utf8)
        guard let aes = try? AES(key: aesKey, blockMode: CBC(iv: iv), padding: .pkcs7),
              let inputData = privateKeyFinal.data(using: .utf8),
              let encryptedBytes = try? aes.encrypt(inputData.bytes)
        else {
            setLoadingView(visible: false)
            return
        }

        let encryptedData = NSData(bytes: encryptedBytes, length: encryptedBytes.count)
        let base64String = encryptedData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))

        // Print keys and salt
        print(publicKeyFinal)
        print(base64String)
        print(salt)
    }

注意:我在我认为很重要的每一行上都添加了一条评论,所以现在你将看到正在发生的事情。

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

https://stackoverflow.com/questions/73454717

复制
相关文章

相似问题

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