在 Swift 中使用 RSA 证书加密
Encrypt using RSA Certificate in Swift
我在 playground 中使用以下代码使用 RSA 加密字符串。我需要使用证书本身进行加密,方法是随时随地提取密钥,而不是单独提取密钥然后加密。
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)
但是它抛出以下异常:
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}))
如何正确地做同样的事情?
所提供的相关代码并未从证书中提取密钥。相反,它会尝试使用证书字符串本身来创建 SecKey
。正确的做法是从证书数据创建一个 SecCertificate
对象,然后使用证书数据创建一个 SecTrust
。然后使用信任,复制 public 密钥以创建 SecKey
对象。
最终代码将如下所示:
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)
唯一的变化是 static func encrypt(string: String, certificate: String?) -> String?
函数。
我在 playground 中使用以下代码使用 RSA 加密字符串。我需要使用证书本身进行加密,方法是随时随地提取密钥,而不是单独提取密钥然后加密。
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)
但是它抛出以下异常:
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}))
如何正确地做同样的事情?
所提供的相关代码并未从证书中提取密钥。相反,它会尝试使用证书字符串本身来创建 SecKey
。正确的做法是从证书数据创建一个 SecCertificate
对象,然后使用证书数据创建一个 SecTrust
。然后使用信任,复制 public 密钥以创建 SecKey
对象。
最终代码将如下所示:
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)
唯一的变化是 static func encrypt(string: String, certificate: String?) -> String?
函数。