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 結(jié)構(gòu)體用來存儲已經(jīng)生成的私鑰和公鑰

通過密鑰字符串生成 SecKey朵逝,加簽,驗簽

  • 詳細(xì)代碼
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 用來標(biāo)識要生成的是私鑰(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 ? "成功" : "失敗")")
}
  • 打印結(jié)果
明文:我是明文
簽名:tD2TjObA/NBRfHjbd3wT4KyAuo+yMWiIXJHVA3qOYMP4ow/WJKzrtaSVQT/COt3ZNMhYY1MTn5syemJ3tcAcFvJtIyprN+rnJMLR9Yu8rrh5yfOa/t55pMsedobUt3ER7SCI5oosyVtvO0EojDK5SG1OFuT9GgfbnSNoFkf2blK7bnuEiLvnlSw/TukKusqeX2OiatvL1qtE3Z0b9RKZRaFl99o/pVo+D5vNGG+K5A9dt6vG/gI0OZYR9YZHT1GIOAryFBejRDeuqP3vniQL0AJRjYXr+cZ4LkiFV1w8X61+Qz6udD6pjeYou3kBwKJOF08mcu+ot9DIh508dQfUtw==
驗簽成功
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市答倡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驴党,老刑警劉巖瘪撇,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡设江,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門攘轩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叉存,“玉大人,你說我怎么就攤上這事度帮〖吣螅” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵笨篷,是天一觀的道長瞳秽。 經(jīng)常有香客問我,道長率翅,這世上最難降的妖魔是什么练俐? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮冕臭,結(jié)果婚禮上腺晾,老公的妹妹穿的比我還像新娘。我一直安慰自己辜贵,他們只是感情好悯蝉,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著托慨,像睡著了一般鼻由。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厚棵,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天蕉世,我揣著相機與錄音,去河邊找鬼婆硬。 笑死讨彼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柿祈。 我是一名探鬼主播哈误,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躏嚎!你這毒婦竟也來了蜜自?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卢佣,失蹤者是張志新(化名)和其女友劉穎重荠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虚茶,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡戈鲁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年仇参,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婆殿。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡诈乒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婆芦,到底是詐尸還是另有隱情怕磨,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布消约,位于F島的核電站肠鲫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏或粮。R本人自食惡果不足惜导饲,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氯材。 院中可真熱鬧帜消,春花似錦、人聲如沸浓体。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽命浴。三九已至娄猫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間生闲,已是汗流浹背媳溺。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碍讯,地道東北人悬蔽。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像捉兴,于是被迫代替她去往敵國和親蝎困。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容