我想知道如何从一个字符串加载RSA公钥并用它加密另一个字符串。公钥类似于:
let key = """ -----BEGIN PUBLIC KEY----- blah blah blah -----END PUBLIC KEY-----"""
我更愿意在没有外部图书馆的情况下完成这项工作,但如果这能让事情变得更容易,我愿意使用它们。提前谢谢。
您拥有的关键数据是PEM编码的。然而,苹果支持DER编码,以确保其安全API。因此,首先我们必须将关键数据转换为正确的格式。下面的示例是使用随机RSA密钥创建的,该密钥将公钥导出为PEM格式。PEM标头可能因库而异,因此在继续进行DER转换之前,请确保删除了标记。
var pem = "-----BEGIN RSA PUBLIC KEY-----nMIIBCgKCAQEAs6AofVx+UAXcVjnIU0Z5SAGO/LPlTunA9zi7jNDcIrZTR8ULHTrmnaSAg/ycNR1/wUeac617RrFeQuoPSWjhZPRJrMa3faVMCqTgV2AmaPgKnPWBrY2irnGhnCnIAvD3sitCEKultjCstrTA71Jo/BuVaj6BVgaA/Qn3U9mQ+4JiEFiTxy4kOFnes1/WwTLjRQYVf42oG350bTKw9F0MklTTZdiZKCQtc3op86A7VscFhwusY0CaZfBnlRDnTgTMoUhZJpKSLZae93NVFSJY1sUANPZg8TzujqhRKt0g5HR/Ud61icvBbcx8n+a3NzmuwPylvp5m6hz/l14Y7UZ8UT5deywIDAQABn-----END RSA PUBLIC KEY-----n"
// Remove headers and footers from the PEM, leaving us with DER encoded data split by new lines
[
"-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----",
"-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----"
].forEach { pem = pem.replacingOccurrences(of: $0, with: "") }
// Construct DER data from the remaining PEM data
let der = Data(base64Encoded: pem, options: .ignoreUnknownCharacters)!
现在我们有了DER编码的数据,是时候构建我们的密钥了。首先,创建描述密钥的属性,然后根据DER数据创建密钥。请注意,der
的类型是Data
,而不是String
。一般来说,加密操作发生在Data
上。然而,安全API使用CFData
,但是可以容易地交换它们(as CFData
或as Data
(。属性字典也是如此。
// Key generation attributes
let attributes: [String: Any] = [
String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
String(kSecAttrKeyClass): kSecAttrKeyClassPublic,
String(kSecAttrKeySizeInBits): der.count * 8
]
// For simplicity I force unwrap here. The nil parameter can be used to extract an error
let key = SecKeyCreateWithData(der as CFData, attributes as CFDictionary, nil)!
既然我们有了密钥,我们就可以用它来加密了。但是,请注意,RSA不能加密大量数据(从技术上讲,这是不正确的,你可以创建数据块并以这种方式进行加密,但RSA并不适合这样做。如果你想这样做,请阅读密钥交换和对称加密。RSA不适合这种行为(。还要注意,OAEP(如示例中所用(有一个随机因素。这意味着每次运行此代码时,密文输出都会有所不同。这并不意味着它不起作用,它只是OAEP的一个财产。我还想指出,当能够支持OAEP时,应该避免PKCS1填充。
// An example message to encrypt
let plainText = "This is my secret".data(using: .utf8)!
// Perform the actual encryption
// Again force unwrapping for simplicity
let cipherText = SecKeyCreateEncryptedData(key, .rsaEncryptionOAEPSHA256, plainText as CFData, nil)! as Data
在上述示例中,使用了.rsaEncryptionOAEPSHA256
。这是RSA可用的加密算法之一:
.rsaEncryptionRaw
.rsaEncryptionPKCS1
.rsaEncryptionOAEPSHA1
.rsaEncryptionOAEPSHA224
.rsaEncryptionOAEPSHA256
.rsaEncryptionOAEPSHA384
.rsaEncryptionOAEPSHA512
我强烈建议使用OAEP变体之一,但这取决于您。我希望这能有所帮助。SecKeyCreateEncryptedData
自10.12起可用于macOS。你可以在这里阅读更多关于它的信息。