Swift RSA 加签验签

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.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==
验签成功

你可能感兴趣的:(Swift RSA 加签验签)