我正在尝试生成一个RSA对密钥,然后将一个X.509证书添加到公钥的头部。为此,我使用了库SwiftyRSA
问题是,当我将X.509证书添加到报头时,我无法解析公钥。当我在之后打印公钥时,它仍然显示与没有证书的相同。
但是,当我打印字节时,它会显示不同的字节,如果没有证书,它将显示270个字节,而证书则显示294字节。这意味着它正在添加证书,但它没有使用证书解析它。
在深入阅读了SwiftyRSA库之后,它说:
警告:存储(使用SwiftyRSA的方法)或创建PublicKey实例将自动从键中删除标头。有关更多信息,请参见上面的引擎盖下面。
如果值得一提的话,甚至还有那个箱子还在那里。
我仍在寻找解决办法,但找不到任何解决办法。我试图实现的代码:
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证书解析公钥?如有任何贡献,我将不胜感激。
发布于 2022-09-10 22:27:39
如前所述,您将无法使用x509
创建SwiftyRSA
证书。实际上,您可以使用安全性框架来完成这一任务。
首先,您需要创建Data
的扩展,它将用于将证书添加到公钥。
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
并将您的代码更改为:
// 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)
}
注意:我在我认为很重要的每一行上都添加了一条评论,所以现在你将看到正在发生的事情。
https://stackoverflow.com/questions/73454717
复制相似问题