Mac 终端生成密钥
- 生成私钥
openssl genrsa -out rsa_private_key.pem 2048
- 生成公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
- 生成证书
openssl req -new -key rsa_private_key.pem -out certificate.csr
生成的密钥字符串
struct RSAKey {
static let privateKey = """
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtxt4MWNQdHp3FE03wHNoyAV63vvuOG47ToObtu9Z2ik6KQ1I
rDfjOIjmD9P6F132Bw2VnkTy+zAXelnSYMiRcagTsXlGcI7SyG8dwc3aU12fgph0
dBL5wIGWDVMqw6RJsEUYoV1ueaUCPiKr1jQGQpJ8Jlg04mj6glWx4G3mkvOc3nSq
u915SANdR1BCgvJDhtRi4onLQcAUvRJOe8cEHhlAX6z45R8/yfkP9OMENAlchkQr
2LUr3I7FSUl9q3pCFVmlRiML+IPySj3cqA6+8Gz2ZST8+8HfLCkcDC9e8AMZcJEx
5sm0wk0TdFtl9o7SGAFcMR9CG9zWji7Z4SlA3QIDAQABAoIBAQCJ+JLadAEdo2Gy
1HRb+RpNDYQGHULlFnptsNFWSIgl0MbYRAAsdHgsE0t3Rby+erh1nBDPDxkfmJ84
PBI/hyHAyGr+YWloStYc3U1IyTnnczZMC2BETkAOhBZyt+YTQOmdfpMOk/44ftNv
ymQ8pTrKUuJlajV/HKcWKkg72dPRiaPC/tCANZQLNjgylQUu3u1wEiCixBa+4lkO
Uccldxy+7P9dzFTZJH/rBqxPCgHhajpSoBnFZJAC22Wk81QvRPS/JfbBG7wdxI7+
iuxuH69bKHrZHPAxGpn0LqfsNvgJ5G/2jwyy/GkZDpNYsgjnKcAgyCsOCTNppO+J
f5Ly6ljBAoGBAOmZmdeMkBxVPYOiKi37zJXwutvhKEos3I/jbTcaFnXaFpvP88vb
XXnsy4bgFQ6Pm61ZMyguYO/Hn6LYjddDmM7C2yzWBIMFVnXMiTVtNUoXTbIH/8CC
+Mz4O5ztITe1AU0D+aUzULGLjKv6LhEAAUYRAyrhR0y+BKNQYFyoHTRVAoGBAMiq
YHEgvAqxlkDIh2hAVQce2PYTI0RJwBIPmK71H5j3JGZmda0JILqzLw176gV3k0Uq
6wX65fD/psB683INy9fZ7fMGgbsnswDdqdBAUBdtPgzQO6fgEZ83S1FCKuceqHT5
Wuj/hxeRvoE2+/tIYqWyM18oppFEoJxCF99izaJpAoGAFl+s2XVQFDah1qrAiXj1
hmLxMsAlAL29PlbVDhMElbMWuUO4oQzYriXc9IUf3y4oBflmKfIPPMgM5ScCptyF
lUAah/fTpMztFAlMFv7nvLnwqh2UBFdHBzK7WvNnXBONFVhNH+KDVw37ojkrElvC
w3g7qm67SoFkplO7dwRvD6UCgYBux0A+s+ebr7ZXRV0bfIh0Sd9U2fPaOyzBy8Jq
tAAhni6GKYJFaIidCVashwAGzKCMysi8oGpYxYn1MOs8x8kE/NaUF79+5se3bqfU
w+xzQmfDAyIr51NTJl96GKE+vnoZOZ+qiYa2yEr3YrdxXeC3wM0Dd5mdENnp6cLs
G8uSIQKBgEGR6KtnB2OOJObRfOCO3+asXoPP4kr4WnFeahvNOsKA+6FCYxljYX3J
JemPi6eaZmIlXMqSgPjPjGNRv7vZbiCaROFdzXrgZbGuN7P2GLDI5Oq0fsfktd3y
adXgXI4TPZ7/hw0o9Rpl63eIfaTxcCJM19VsNCWHdccF6LxTCewS
-----END RSA PRIVATE KEY-----
"""
static let publicKey = """
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtxt4MWNQdHp3FE03wHNo
yAV63vvuOG47ToObtu9Z2ik6KQ1IrDfjOIjmD9P6F132Bw2VnkTy+zAXelnSYMiR
cagTsXlGcI7SyG8dwc3aU12fgph0dBL5wIGWDVMqw6RJsEUYoV1ueaUCPiKr1jQG
QpJ8Jlg04mj6glWx4G3mkvOc3nSqu915SANdR1BCgvJDhtRi4onLQcAUvRJOe8cE
HhlAX6z45R8/yfkP9OMENAlchkQr2LUr3I7FSUl9q3pCFVmlRiML+IPySj3cqA6+
8Gz2ZST8+8HfLCkcDC9e8AMZcJEx5sm0wk0TdFtl9o7SGAFcMR9CG9zWji7Z4SlA
3QIDAQAB
-----END PUBLIC KEY-----
"""
}
RSAKey 结构体用来存储已经生成的私钥和公钥
通过密钥字符串生成 SecKey,加签,验签
- 详细代码
import Foundation
/// 密钥类型
enum KeyType {
case publicKey
case privateKey
}
struct RSASigner {
/// 通过密钥字符串获取 SecKey 类型的密钥
/// - Parameter keyString: 密钥字符串
/// - Parameter keyType: 密钥类型
static func getSecKey(with keyString: String,keyType: KeyType) -> SecKey? {
let strippedKey = String(keyString.filter { !" \n\t\r".contains($0) })
let pemComponents = strippedKey.components(separatedBy: "-----")
guard pemComponents.count >= 5 else { return nil }
guard let keyData = Data(base64Encoded: pemComponents[2]) else { return nil }
let keyClass = keyType == .publicKey ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate
let sizeInBits = keyData.count * MemoryLayout<UInt8>.size
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: keyClass,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits)
]
guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, nil) else { return nil }
return key
}
/// 使用 RSA 算法签名
/// - Parameter text: 明文
/// - Parameter privateKey: 密钥
static func sign(text: String, with privateKey: SecKey) -> String? {
guard let data = text.data(using: .utf8) else { return nil }
guard let signedData = SecKeyCreateSignature(privateKey, .rsaSignatureMessagePKCS1v15SHA256, data as CFData , nil) as Data? else { return nil }
return signedData.base64EncodedString()
}
/// 验证签名
/// - Parameter signature: 签名字符串
/// - Parameter text: 明文
/// - Parameter publicKey: 公钥
static func verify(signature: String, text: String, with publicKey: SecKey) -> Bool {
guard let signedData = text.data(using: .utf8) else { return false }
guard let signature = Data(base64Encoded: signature) else { return false }
return SecKeyVerifySignature(publicKey, .rsaSignatureMessagePKCS1v15SHA256, signedData as CFData, signature as CFData,nil)
}
}
上面的代码可以通过 RSA 私钥字符串或公钥字符串(如上面所示)生成 Swift 中需要的 SecKey 类型的密钥。使用 SecKey 类型的私钥字符串用来加签,使用 SecKey 类型的公钥用来验签。
定义了一个枚举类型
KeyType
用来标识要生成的是私钥(publicKey
)还是公钥(privateKey
)使用
getSecKey(with,keyType)
方法来获取SecKey
类型的密钥使用
sign(text: with:)
方法类生成签名使用
verify(signature: text: with)
来验证签名是否正确
- 使用示例
func testSignAndVerify() {
let text = "我是明文"
guard let privateKey = RSASigner.getSecKey(with: RSAKey.privateKey, keyType: .privateKey) else {
return
}
guard let signature = RSASigner.sign(text: text, with: privateKey) else {
return
}
guard let pubKey = RSASigner.getSecKey(with: RSAKey.publicKey, keyType: .publicKey) else {
return
}
let result = RSASigner.verify(signature: signature, text: text, with: pubKey)
print("明文:\(text)")
print("签名:\(signature)")
print("验签\(result ? "成功" : "失败")")
}
- 打印结果
明文:我是明文
签名:tD2TjObA/NBRfHjbd3wT4KyAuo+yMWiIXJHVA3qOYMP4ow/WJKzrtaSVQT/COt3ZNMhYY1MTn5syemJ3tcAcFvJtIyprN+rnJMLR9Yu8rrh5yfOa/t55pMsedobUt3ER7SCI5oosyVtvO0EojDK5SG1OFuT9GgfbnSNoFkf2blK7bnuEiLvnlSw/TukKusqeX2OiatvL1qtE3Z0b9RKZRaFl99o/pVo+D5vNGG+K5A9dt6vG/gI0OZYR9YZHT1GIOAryFBejRDeuqP3vniQL0AJRjYXr+cZ4LkiFV1w8X61+Qz6udD6pjeYou3kBwKJOF08mcu+ot9DIh508dQfUtw==
验签成功