Swift 从字符串加载 RSA Public 密钥 (MacOS)
Swift Load RSA Public Key from String (MacOS)
我想知道如何从字符串加载 RSA Public 密钥并用它加密另一个字符串。
public 键类似于:
let key = """ -----BEGIN PUBLIC KEY----- blah blah blah -----END PUBLIC KEY-----"""
我宁愿在没有外部库的情况下执行此操作,但如果它使事情变得更容易,我愿意使用它们。
提前致谢。
您拥有的关键数据 PEM encoded. However, Apple supports DER encoding 是为了他们的安全 API。因此,首先我们必须将您的关键数据转换为正确的格式。下面的示例是使用随机 RSA 密钥创建的,将 public 密钥导出为 PEM 格式。 PEM headers 可能因库而异,因此请确保在继续进行 DER 转换之前删除标签。
var pem = "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAs6AofVx+UAXcVjnIU0Z5SAGO/LPlTunA9zi7jNDcIrZTR8ULHTrm\naSAg/ycNR1/wUeac617RrFeQuoPSWjhZPRJrMa3faVMCqTgV2AmaPgKnPWBrY2ir\nGhnCnIAvD3sitCEKultjCstrTA71Jo/BuVaj6BVgaA/Qn3U9mQ+4JiEFiTxy4kOF\nes1/WwTLjRQYVf42oG350bTKw9F0MklTTZdiZKCQtc3op86A7VscFhwusY0CaZfB\nlRDnTgTMoUhZJpKSLZae93NVFSJY1sUANPZg8TzujqhRKt0g5HR/Ud61icvBbcx8\n+a3NzmuwPylvp5m6hz/l14Y7UZ8UT5deywIDAQAB\n-----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: [=10=], 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。您可以阅读更多相关信息 here。
我想知道如何从字符串加载 RSA Public 密钥并用它加密另一个字符串。 public 键类似于:
let key = """ -----BEGIN PUBLIC KEY----- blah blah blah -----END PUBLIC KEY-----"""
我宁愿在没有外部库的情况下执行此操作,但如果它使事情变得更容易,我愿意使用它们。 提前致谢。
您拥有的关键数据 PEM encoded. However, Apple supports DER encoding 是为了他们的安全 API。因此,首先我们必须将您的关键数据转换为正确的格式。下面的示例是使用随机 RSA 密钥创建的,将 public 密钥导出为 PEM 格式。 PEM headers 可能因库而异,因此请确保在继续进行 DER 转换之前删除标签。
var pem = "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAs6AofVx+UAXcVjnIU0Z5SAGO/LPlTunA9zi7jNDcIrZTR8ULHTrm\naSAg/ycNR1/wUeac617RrFeQuoPSWjhZPRJrMa3faVMCqTgV2AmaPgKnPWBrY2ir\nGhnCnIAvD3sitCEKultjCstrTA71Jo/BuVaj6BVgaA/Qn3U9mQ+4JiEFiTxy4kOF\nes1/WwTLjRQYVf42oG350bTKw9F0MklTTZdiZKCQtc3op86A7VscFhwusY0CaZfB\nlRDnTgTMoUhZJpKSLZae93NVFSJY1sUANPZg8TzujqhRKt0g5HR/Ud61icvBbcx8\n+a3NzmuwPylvp5m6hz/l14Y7UZ8UT5deywIDAQAB\n-----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: [=10=], 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。您可以阅读更多相关信息 here。