在Swift中使用RSA证书进行加密 [英] Encrypt using RSA Certificate in Swift
问题描述
我在操场上使用以下代码使用RSA加密字符串.我需要使用证书本身来进行加密,方法是在旅途中提取密钥,而不是单独提取密钥然后进行加密.
I used the following code in a playground to Encrypt a string using RSA. I need the encryption to happen using certificate itself, by extracting the key on the go, rather than the key getting extracted separately and then encrypting.
import Foundation
import Security
struct RSA {
static func encrypt(string: String, publicKey: String?) -> String? {
guard let publicKey = publicKey else { return nil }
let keyString = publicKey.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "").replacingOccurrences(of: "-----END CERTIFICATE-----", with: "").replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "").replacingOccurrences(of: " ", with: "")
print(keyString)
guard let data = Data(base64Encoded: keyString) else { return nil }
print(data)
var attributes: CFDictionary {
return [kSecAttrKeyType : kSecAttrKeyTypeRSA,
kSecAttrKeyClass : kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits : 2048,
kSecReturnPersistentRef : kCFBooleanTrue as Any] as CFDictionary
}
var error: Unmanaged<CFError>? = nil
guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
print(error.debugDescription)
return nil
}
return encrypt(string: string, publicKey: secKey)
}
static func encrypt(string: String, publicKey: SecKey) -> String? {
let buffer = [UInt8](string.utf8)
var keySize = SecKeyGetBlockSize(publicKey)
var keyBuffer = [UInt8](repeating: 0, count: keySize)
// Encrypto should less than key length
guard SecKeyEncrypt(publicKey, SecPadding.PKCS1, buffer, buffer.count, &keyBuffer, &keySize) == errSecSuccess else { return nil }
return Data(bytes: keyBuffer, count: keySize).base64EncodedString()
}
}
var pemString = "-----BEGIN CERTIFICATE-----##Base 64 encoded certificate string##-----END CERTIFICATE-----"
let password = "abcde"
let encryptedPassword = RSA.encrypt(string: password, publicKey: pemString)
print(encryptedPassword as Any)
但是它会引发以下异常:
However it is throwing the following exception:
可选的(Swift.Unmanaged< __ C.CFErrorRef>(_ value:错误Domain = NSOSStatusErrorDomain Code = -50"RSA公钥创建自数据失败" UserInfo = {NSDescription =从数据创建RSA公钥失败}))
Optional(Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "RSA public key creation from data failed" UserInfo={NSDescription=RSA public key creation from data failed}))
如何正确执行相同的操作?
How to do the same properly?
推荐答案
所提供的代码不会从证书中提取密钥.而是尝试使用证书字符串本身创建 SecKey
.正确的方法是从证书数据创建 SecCertificate
对象,然后使用证书数据创建 SecTrust
.然后使用信任关系,复制公钥以创建 SecKey
对象.
The code provided in question doesn't extract the Key from certificate. Rather, it tries to create the SecKey
using the certificate string itself. The correct way to do the same is to create a SecCertificate
object from the certificate data, then create a SecTrust
using the certificate data. Then using the trust, copy the public key to make SecKey
object.
最终代码如下:
import Foundation
import Security
struct RSA {
static func encrypt(string: String, certificate: String?) -> String? {
guard let certificate = certificate else { return nil }
let certificateString = certificate.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "").replacingOccurrences(of: "-----END CERTIFICATE-----", with: "").replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "").replacingOccurrences(of: " ", with: "")
print(certificateString)
// Convert the certificate string to Data
guard let data = Data(base64Encoded: certificateString) else { return nil }
print(data)
// Create SecCertificate object using certificate data
guard let cer = SecCertificateCreateWithData(nil, data as NSData) else { return nil }
var trust: SecTrust?
// Retrieve a SecTrust using the SecCertificate object. Provide X509 as policy
let status = SecTrustCreateWithCertificates(cer, SecPolicyCreateBasicX509(), &trust)
// Check if the trust generation is success
guard status == errSecSuccess else { return nil }
// Retrieve the SecKey using the trust hence generated
guard let secKey = SecTrustCopyPublicKey(trust!) else { return nil }
return encrypt(string: string, publicKey: secKey)
}
static func encrypt(string: String, publicKey: SecKey) -> String? {
let buffer = [UInt8](string.utf8)
var keySize = SecKeyGetBlockSize(publicKey)
var keyBuffer = [UInt8](repeating: 0, count: keySize)
// Encrypto should less than key length
guard SecKeyEncrypt(publicKey, SecPadding.PKCS1, buffer, buffer.count, &keyBuffer, &keySize) == errSecSuccess else { return nil }
return Data(bytes: keyBuffer, count: keySize).base64EncodedString()
}
}
var pemString = "-----BEGIN CERTIFICATE-----##Base 64 encoded certificate string##-----END CERTIFICATE-----"
let password = "abcde"
let encryptedPassword = RSA.encrypt(string: password, certificate: pemString)
print(encryptedPassword as Any)
唯一的变化是在静态函数crypto(字符串:字符串,证书:字符串?)->字符串?
函数.
这篇关于在Swift中使用RSA证书进行加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!