RSA 加密

使用Swift原生进行RSA加密处理:

一、导入:

import CommonCrypto
二、 使用方法:
private func rsa() {
    let PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArdklK4kIsOMuxTZ8jG1PRPfXqSDmaCIQ+xEpIRSssQ6jiuvhYZTMUbV22osgtivuyKdnHm+cvzGuZCSB8QFyCcM7l09HZVs0blLkrBAU5CVSv+6BzPQTVJytoi/VO4mlf6me1Y9bXWrrPw1YtC1mnB2Ix9cuaxOLpucglfGbUaGEigsUZMTD2vuEODN5cJi39ap+G9ILitbrnt+zsW9354pokVnHw4Oq837Fd7ZtP0nAA5F6nE3FNDGQqLy2WYRoKC9clDecD8T933azUD98b5FSUGzIhwiuqHHeylfVbevbBW91Tvg9s7vUMr0Y2YDpEmPAf0q4PlDt8QsjctT9kQIDAQAB"

    let PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCt2SUriQiw4y7FNnyMbU9E99epIOZoIhD7ESkhFKyxDqOK6+FhlMxRtXbaiyC2K+7Ip2ceb5y/Ma5kJIHxAXIJwzuXT0dlWzRuUuSsEBTkJVK/7oHM9BNUnK2iL9U7iaV/qZ7Vj1tdaus/DVi0LWacHYjH1y5rE4um5yCV8ZtRoYSKCxRkxMPa+4Q4M3lwmLf1qn4b0guK1uue37Oxb3fnimiRWcfDg6rzfsV3tm0/ScADkXqcTcU0MZCovLZZhGgoL1yUN5wPxP3fdrNQP3xvkVJQbMiHCK6ocd7KV9Vt69sFb3VO+D2zu9QyvRjZgOkSY8B/Srg+UO3xCyNy1P2RAgMBAAECggEAInVN9skcneMJ3DEmkrb/5U2yw2UwBifqcbk/C72LVTTvmZOTgsH5laCARGUbQMCIfeEggVniGcuBI3xQ/TIqJmE6KI2gOyjOxadMiAZP/cCgHEbsF3Gxey3rBKCyhTCNSzaVswLNO0D8C+1bTatKEVuRRvsRykt/fL+HJ/FRteYYO9LuLv2WESJGE6zsi03P6snNiRracvYqz+Rnrvf1Xuyf58wC1C6JSjZ9D6tootPDBTEYaIIbpEnV+qP/3k5OFmA9k4WbkZI6qYzqSK10bTQbjMySbatovnCD/oqIUOHLwZpL051E9lz1ZUnDbrxKwT0BIU7y4DYaHSzrKqRsIQKBgQDTQ9DpiuI+vEj0etgyJgPBtMa7ClTY+iSd0ccgSE9623hi1CHtgWaYp9C4Su1GBRSF0xlQoVTuuKsVhI89far2Z0hR9ULr1J1zugMcNESaBBC17rPoRvXPJT16U920Ntwr00LviZ/DEyvmpVDagYy+mSK0Wq+kH7p5aR5zAHXWrQKBgQDSqQ6TBr5bDMvhpRi94unghiWyYL6srSRV9XjqDpiNU+yFwCLzSG610DyXFa3pV138P+ryunqg1LtKsOOtZJONzbS1paINnwkvfwzMpI7TjCq1+8rxeEhZ3AVmumDtPQK+YfGbxCQ+LAOJZOu8lGv1O7tsbXFp0vh5RmWHWHvy9QKBgCMGPi9JsCJ4cpvdddQyizLk9oFxwAlMxx9G9P08H7kdg4LW6l0Gs+yg/bBf86BFHVbmXW8JoBwHj418sYafO+Wnz8yOna6dTBEwiG13mNvzypVu4nKiuQPDh8Ks/rdu1OeLGbC+nzbnCcMuKw5epee/WYqO8kmCXRbdv4ePTvntAoGBAJYQ9F7saOI3pW2izJNIeE8HgQcnP+2GkeHiMjaaGzZiWJWXH86rBKLkKqV+PhuBr2QorFgpW34CzUER7b7xbOORbHASA/UsG8EIArgtacltimeFbTbC9td8kyRxFOcrlS7GWvUZrq/TbtmLWRtHp/hUitlcxXQbZAIQkfbuo62ZAoGBAKBURvLGM0ethkvUHFyGae2YGG/s+u+EYd2zNba7A6qnfzrlMHVPiPO6lx31+HwhuJ0tBZWMJKhEZ5PWByZzreVKVH5fE5LoQLo+B3VCTyTc1fJ9RKLAPrPqHuvzPHHP/n84XHGeit3e4ytd3Mm/6CNbrg7xux2M4RDQmN//1UOY"

    var ss = "hello world"
    print("1--:\(ss)")
    ss = RSA.encryptString(ss, publicKey: PUBLIC_KEY)!
    print("2--:\(ss)")
    ss = RSA.decryptString(ss, privateKey: PRIVATE_KEY) ?? ""
    print("3--:\(ss)")
}
三、打印结果:
1--:hello world
2--:cS0pr1GuvXMO6lz7IX8nXJh1+bW2immH4zh01g198eXG+NMo9anqn/RSZoN3dsdH

kzbpgHcgcQ1Yjz3PodFIdHcVXMdW09ujscZMdxuYaKmW/hQECeSLpnRZV8PdRJGf

nTrss6hw4zd8xrpTeD/NkKERy0/AqgOx+bxfG/6uoc5jwSMqwNw20jwRksrbjA7F

nAL8KM3PvhY320cOowvOIbE1t+VpQz1feKzbvgIJNBEPoH9ZihjRMA7kTayqLson

uZCv/4b8OQ0aSNFcw+NlbjqSCV+XyyipQvewDJycvBSxmYAeKyApPVrY3cu09fjn

xAKlLLZaoVR3aUpZ9W9UrQ==
3--:hello world
四、加密代码
struct RSA {
    
    //MARK:-  encrypt or decrypt by SecKey String
    
    /// 使用私钥字符串加密Data
    /// - Parameters:
    ///   - data: 需加密的Data
    ///   - privateKey: 私钥字符串
    /// - Returns: 加密后Data
    static func encryptData(_ data: Data, privateKey: String) -> Data? {
        let secKey = addPrivateKey(privateKey)
        if secKey == nil {
            return nil
        }
        return encrypt(data, with: secKey!, and: true)
    }
    
    /// 使用私钥字符串加密String
    /// - Parameters:
    ///   - string: 需加密的String
    ///   - privateKey: 私钥字符串
    /// - Returns: 加密后String
    static func encryptString(_ string: String, privateKey: String) -> String? {
        guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKey: privateKey) else {
            return nil
        }
        return base64_encode_data(data)
    }
    
    /// 使用私钥字符串解密Data
    /// - Parameters:
    ///   - data: 需解密的Data
    ///   - privateKey: 私钥字符串
    /// - Returns: 解密后Data
    static func decryptData(_ data: Data, privateKey: String) -> Data? {
        let secKey = addPrivateKey(privateKey)
        if secKey == nil {
            return nil
        }
        return decrypt(data, with: secKey!)
    }
    
    /// 使用私钥字符串解密String
    /// - Parameters:
    ///   - string: 需解密的String
    ///   - privateKey: 私钥字符串
    /// - Returns: 解密后String
    static func decryptString(_ string: String, privateKey: String) -> String? {
        var data = base64_decode(string)
        data = decryptData(data!, privateKey: privateKey)
        if data == nil {
            return nil
        }
        return String.init(data: data!, encoding: String.Encoding.utf8)
    }
    
    /// 使用公钥字符串加密Data
    /// - Parameters:
    ///   - data: 需加密的Data
    ///   - publicKey: 公钥字符串
    /// - Returns: 加密后Data
    static func encryptData(_ data: Data, publicKey: String) -> Data? {
        let secKey = addPublicKey(publicKey)
        if secKey == nil {
            return nil
        }
        return encrypt(data, with: secKey!, and: false)
    }
    
    /// 使用公钥字符串加密String
    /// - Parameters:
    ///   - string: 需加密的String
    ///   - publicKey: 公钥字符串
    /// - Returns: 加密后String
    static func encryptString(_ string: String, publicKey: String) -> String? {
        guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKey: publicKey) else {
            return nil
        }
        return base64_encode_data(data)
    }
    
    /// 使用公钥字符串解密Data
    /// - Parameters:
    ///   - data: 需解密的Data
    ///   - publicKey: 公钥字符串
    /// - Returns: 解密后Data
    static func decryptData(_ data: Data, publicKey: String) -> Data? {
        let secKey = addPublicKey(publicKey)
        if secKey == nil {
            return nil
        }
        return decrypt(data, with: secKey!)
    }
    
    /// 使用公钥字符串解密String
    /// - Parameters:
    ///   - string: 需解密的String
    ///   - publicKey: 公钥字符串
    /// - Returns: 解密后String
    static func decryptString(_ string: String, publicKey: String) -> String? {
        var data = base64_decode(string)
        data = decryptData(data!, publicKey: publicKey)
        if data == nil {
            return nil
        }
        return String.init(data: data!, encoding: String.Encoding.utf8)
    }
    
    
    
    //MARK:- encrypt or decrypt by SecKey path
    
    
    /// 使用私钥证书路径加密Data
    /// - Parameters:
    ///   - data: 需加密的Data
    ///   - privateKeyPath: 私钥证书路径
    /// - Returns: 加密后Data
    static func encryptData(_ data: Data, privateKeyPath: String) -> Data? {
        let secKey = loadPrivateKey(privateKeyPath)
        if secKey == nil {
            return nil
        }
        return encrypt(data, with: secKey!, and: true)
    }
    
    /// 使用私钥证书路径加密String
    /// - Parameters:
    ///   - string: 需加密的String
    ///   - privateKeyPath: 私钥证书路径
    /// - Returns: 加密后String
    static func encryptString(_ string: String, privateKeyPath: String) -> String? {
        guard let data = encryptData(string.data(using: String.Encoding.utf8)!, privateKeyPath: privateKeyPath) else {
            return nil
        }
        return base64_encode_data(data)
    }
    
    /// 使用私钥证书路径解密Data
    /// - Parameters:
    ///   - data: 需解密的Data
    ///   - privateKeyPath: 私钥证书路径
    /// - Returns: 解密后Data
    static func decryptData(_ data: Data, privateKeyPath: String) -> Data? {
        let secKey = loadPrivateKey(privateKeyPath)
        if secKey == nil {
            return nil
        }
        return decrypt(data, with: secKey!)
    }
    
    /// 使用私钥证书路径解密String
    /// - Parameters:
    ///   - string: 需解密的String
    ///   - privateKeyPath: 私钥证书路径
    /// - Returns: 解密后String
    static func decryptString(_ string: String, privateKeyPath: String) -> String? {
        var data = base64_decode(string)
        data = decryptData(data!, privateKeyPath: privateKeyPath)
        if data == nil {
            return nil
        }
        return String.init(data: data!, encoding: String.Encoding.utf8)
    }
    
    /// 使用公钥证书路径加密Data
    /// - Parameters:
    ///   - data: 需加密的Data
    ///   - publicKeyPath: 公钥证书路径
    /// - Returns: 加密后Data
    static func encryptData(_ data: Data, publicKeyPath: String) -> Data? {
        let secKey = loadPublicKey(publicKeyPath)
        if secKey == nil {
            return nil
        }
        return encrypt(data, with: secKey!, and: false)
    }
    
    /// 使用公钥证书路径加密String
    /// - Parameters:
    ///   - string: 需加密的String
    ///   - publicKeyPath: 公钥证书路径
    /// - Returns: 加密后String
    static func encryptString(_ string: String, publicKeyPath: String) -> String? {
        guard let data = encryptData(string.data(using: String.Encoding.utf8)!, publicKeyPath: publicKeyPath) else {
            return nil
        }
        return base64_encode_data(data)
    }
    
    /// 使用公钥证书路径解密Data
    /// - Parameters:
    ///   - data: 需解密的Data
    ///   - publicKeyPath: 公钥证书路径
    /// - Returns: 解密后Data
    static func decryptData(_ data: Data, publicKeyPath: String) -> Data? {
        let secKey = loadPublicKey(publicKeyPath)
        if secKey == nil {
            return nil
        }
        return decrypt(data, with: secKey!)
    }
    
    /// 使用公钥证书路径解密String
    /// - Parameters:
    ///   - string: 需解密的String
    ///   - publicKeyPath: 公钥证书路径
    /// - Returns: 解密后String
    static func decryptString(_ string: String, publicKeyPath: String) -> String? {
        var data = base64_decode(string)
        data = decryptData(data!, publicKeyPath: publicKeyPath)
        if data == nil {
            return nil
        }
        return String.init(data: data!, encoding: String.Encoding.utf8)
    }
    
    
    
    
    
    //MARK:- OTHER
    
    private static func base64_encode_data(_ data: Data) -> String? {
        let newData = data.base64EncodedData(options: Data.Base64EncodingOptions.lineLength64Characters)
        return String.init(data: newData, encoding: String.Encoding.utf8)
    }
    
    private static func base64_decode(_ string: String) -> Data? {
        return Data.init(base64Encoded: string, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)
    }
    
    private static func stripPublicKeyHeader(_ d_key: Data?) -> Data? {
        guard let dKey = d_key else {
            return nil
        }
        let len = dKey.count
        if len == 0 {
            return nil
        }
        
        var cKey = dataToBytes(dKey)
        var index = 0
        
        if cKey[index] != 0x30 {
            return nil
        }
        index += 1
        
        if cKey[index] > 0x80 {
            index += Int(cKey[index]) - 0x80 + 1
        } else {
            index += 1
        }
        
        let swqiod:[CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
                                      0x01, 0x05, 0x00]
        if (memcmp(&cKey[index], swqiod, 15) == 1) {
            return nil
        }
        
        index += 15
        
        if cKey[index] != 0x03 {
            return nil
        }
        index += 1
        
        if cKey[index] > 0x80 {
            index += Int(cKey[index]) - 0x80 + 1
        } else {
            index += 1
        }
        
        if cKey[index] != Unicode.Scalar.init("\0").value {
            return nil
        }
        
        index += 1

        return Data.init(cKey).advanced(by: index)
    }
    
    private static func stripPrivateKeyHeader(_ d_key: Data?) -> Data? {
        guard let dKey = d_key else {
            return nil
        }
        let len = dKey.count
        if len == 0 {
            return nil
        }
        
        var cKey = dataToBytes(dKey)
        var index = 22
        
        if cKey[index] != 0x04 {
            return nil
        }
        index += 1
        
        var cLen = Int(cKey[index])
        index += 1
        let det = cLen & 0x80
        if det == 0 {
            cLen = cLen & 0x7f
        } else {
            var byteCount = Int(cLen & 0x7f)
            if Int(byteCount) + index > len {
                return nil
            }
            var accum = 0
            var ptr = withUnsafePointer(to: &cKey[index]) { $0 }
            index += Int(byteCount)
            while byteCount > 0 {
                accum = (accum << 8) + Int(ptr.pointee)
                ptr = ptr.advanced(by: 1)
                byteCount -= 1
            }
            cLen = accum
        }
        
        return dKey.subdata(in: Range.init(_NSRange.init(location: index, length: Int(cLen)))!)
    }
    
    /// 公钥字符串转SecKey
    /// - Parameter key: 公钥字符串
    /// - Returns: SecKey
    private static func addPublicKey(_ key: String) -> SecKey? {
        var newKey = key
        let spos = newKey.range(of: "-----BEGIN PUBLIC KEY-----")
        let epos = newKey.range(of: "-----END PUBLIC KEY-----")
        if spos != nil && epos != nil {
            newKey = String(newKey[spos!.upperBound...init()
        publicKey[kSecClass as String] = kSecClassKey
        publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA
        publicKey[kSecAttrApplicationTag as String] = d_tag
        SecItemDelete(publicKey as CFDictionary)

        publicKey[kSecValueData as String] = data
        publicKey[kSecAttrKeyClass as String] = kSecAttrKeyClassPublic
        publicKey[kSecReturnPersistentRef as String] = true

        var status = SecItemAdd(publicKey as CFDictionary, nil)

        if status != noErr && status != errSecDuplicateItem {
            return nil
        }

        publicKey.removeValue(forKey: kSecValueData as String)
        publicKey.removeValue(forKey: kSecReturnPersistentRef as String)
        publicKey[kSecReturnRef as String] = NSNumber(value: true)
        publicKey[kSecAttrKeyType as String] = kSecAttrKeyTypeRSA

        var keyRef: CFTypeRef?
        status = SecItemCopyMatching(publicKey as CFDictionary, &keyRef)
        if status != noErr {
            return nil
        }
        return (keyRef as! SecKey)
    }
    
    /// 私钥字符串转SecKey
    /// - Parameter key: 私钥字符串        /// - Returns: SecKey
    private static func addPrivateKey(_ key: String) -> SecKey? {
        var newKey = key
        var spos: Range?
        var epos: Range?
        spos =  newKey.range(of: "-----BEGIN RSA PRIVATE KEY-----")
        if spos != nil {
            epos = newKey.range(of: "-----END RSA PRIVATE KEY-----")
        } else {
            spos = newKey.range(of: "-----BEGIN PRIVATE KEY-----")
            epos = newKey.range(of: "-----END PRIVATE KEY-----")
        }
        if spos != nil && epos != nil {
            newKey = String(newKey[spos!.upperBound...init()
        privateKey[kSecClass] = kSecClassKey
        privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA
        privateKey[kSecAttrApplicationTag] = d_tag
        SecItemDelete(privateKey as CFDictionary)
        
        privateKey[kSecValueData] = data
        privateKey[kSecAttrKeyClass] = kSecAttrKeyClassPrivate
        privateKey[kSecReturnPersistentRef] = true
        
        var persistKey: CFTypeRef?
        var status = SecItemAdd(privateKey as CFDictionary, &persistKey)
        
        if status != noErr && status != errSecDuplicateItem {
            return nil
        }
        
        privateKey.removeValue(forKey: kSecValueData)
        privateKey.removeValue(forKey: kSecReturnPersistentRef)
        privateKey[kSecReturnRef] = true
        privateKey[kSecAttrKeyType] = kSecAttrKeyTypeRSA
        
        var keyRef: CFTypeRef?
        status = SecItemCopyMatching(privateKey as CFDictionary, &keyRef)
        if status != noErr {
            return nil
        }
        return (keyRef as! SecKey)
    }
    
    private static func encrypt(_ data: Data, with secKey: SecKey, and isSign: Bool) -> Data? {
        var srcbuf = dataToBytes(data)
        let srclen = data.count
        
        let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout.size
        var outbuf = [UInt8](repeating: 0, count: block_size)
        let src_block_size = block_size - 11
        
        var ret: Data? = Data.init()
        var index = 0
        while index < srclen {
            var data_len = srclen - index
            if data_len > src_block_size {
                data_len = src_block_size
            }
            
            var outlen = block_size
            var status = noErr
            
            let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 }
            if isSign {
                status = SecKeyRawSign(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen)
            } else {
                status = SecKeyEncrypt(secKey, SecPadding.PKCS1, ptr, data_len, &outbuf, &outlen)
            }
            if status != 0 {
                ret = nil
                break
            } else {
                ret!.append(contentsOf: outbuf[0.. Data? {
        var srcbuf = dataToBytes(data)
        let srclen = data.count
        
        let block_size = SecKeyGetBlockSize(secKey) * MemoryLayout.size
        var outbuf = [UInt8](repeating: 0, count: block_size)
        let src_block_size = block_size
        
        var ret: Data? = Data.init()
        var index = 0
        while index < srclen {
            var data_len = srclen - index
            if data_len > src_block_size {
                data_len = src_block_size
            }
            
            var outlen = block_size
            var status = noErr
            
            let ptr = withUnsafePointer(to: &srcbuf[index]) { $0 }
            status = SecKeyDecrypt(secKey, SecPadding.init(rawValue: 0), ptr, data_len, &outbuf, &outlen)
            
            if status != 0 {
                ret = nil
                break
            } else {
                var idxFirstZero = -1
                var idxNextZero = Int(outlen)
                for i in 0.. SecKey? {
        let data: Data;
        do {
            data = try Data.init(contentsOf: URL.init(fileURLWithPath: path))
        } catch {
            return nil
        }
        
        guard let cert = SecCertificateCreateWithData(nil, data as CFData) else {
            return nil
        }
        let key: SecKey?
        var trust: SecTrust?
        let policy = SecPolicyCreateBasicX509()
        if SecTrustCreateWithCertificates(cert, policy, &trust) == noErr {
            var result = SecTrustResultType.invalid
            if trust != nil {
                if SecTrustEvaluate(trust!, &result) == noErr {
                    key = SecTrustCopyPublicKey(trust!)
                    return key
                }
            }
        }
        return nil
    }
    
    /// 从.p12证书获取私钥
    /// - Parameters:
    ///   - path: .p12证书路径
    ///   - password: ,p12证书密码
    /// - Returns: 私钥
    private static func loadPrivateKey(_ path: String, with password: String = "") -> SecKey? {
        let data: Data;
        do {
            data = try Data.init(contentsOf: URL.init(fileURLWithPath: path))
        } catch {
            return nil
        }
        
        var key: SecKey?
        let options = NSMutableDictionary.init()
        options[kSecImportExportPassphrase as String] = password
        var items: CFArray?
        var securityError = SecPKCS12Import(data as CFData, options, &items)
        if securityError == noErr && CFArrayGetCount(items) > 0 {
            let identityDict = CFArrayGetValueAtIndex(items, 0)
            let appKey = Unmanaged.passUnretained(kSecImportItemIdentity).toOpaque()
            let identityApp = CFDictionaryGetValue((identityDict as! CFDictionary), appKey)
            securityError = SecIdentityCopyPrivateKey(identityApp as! SecIdentity, &key)
            if securityError == noErr {
                return key
            }
        }
        return nil
    }
    
    /// Data转Byte(UInt8)数组
    /// - Parameter data: Data
    /// - Returns: Byte(UInt8)数组
    private static func dataToBytes(_ data: Data) -> [UInt8] {
        let string = dataToHex(data)
        var start = string.startIndex
        return stride(from: 0, to: string.count, by: 2).compactMap { _ in
            let end = string.index(after: start)
            defer {start = string.index(after: end)}
            return UInt8(string[start...end], radix: 16)
        }
    }
    
    /// Data转16进制字符串
    /// - Parameter data: Data
    /// - Returns: 16进制字符串
    private static func dataToHex(_ data: Data) -> String {
        let bytes = [UInt8](data)
        var hex = ""
        for index in 0..

转载自

你可能感兴趣的:(RSA 加密)