• 具体参考文章: 开源框架 RSA_Swift

    具体参考文章:
    开源框架 RSA_Swift

    展开全文
  • iOS Swift RSA

    2018-01-03 10:52:35
    Swift3之后: 参考github链接: https://github.com/TakeScoop/SwiftyRSA Swift3之前: copy 下面三个文件代码到项目中,然后在桥文件 ...-Bridging-Header.h 中加上  #import "NSData+SHA.h" 最后在需要...

    Swift3之后:

    参考github链接:

    https://github.com/TakeScoop/SwiftyRSA

    Swift3之前:

    copy 下面三个文件代码到项目中,然后在桥文件 ...-Bridging-Header.h 中加上 

    #import "NSData+SHA.h"  最后在需要的地方用就好了。

    如publickey加密:

    try SwiftyRSA.encryptString(param as String, publicKeyPEM: MyClass.Constants.RSA_Public_Key as String)

    1.NSData+SHA.h

    #import <Foundation/Foundation.h>
    
    @interface NSData (NSData_SwiftyRSASHA)
    
    - (nonnull NSData*) SwiftyRSASHA1;
    - (nonnull NSData*) SwiftyRSASHA224;
    - (nonnull NSData*) SwiftyRSASHA256;
    - (nonnull NSData*) SwiftyRSASHA384;
    - (nonnull NSData*) SwiftyRSASHA512;
    
    @end

    2.NSData+SHA.m

    
    #import <Foundation/Foundation.h>
    #import <CommonCrypto/CommonCrypto.h>
    
    @implementation NSData (NSData_SwiftyRSASHA)
    
    - (nonnull NSData*) SwiftyRSASHA1 {
        unsigned int outputLength = CC_SHA1_DIGEST_LENGTH;
        unsigned char output[outputLength];
        
        CC_SHA1(self.bytes, (unsigned int) self.length, output);
        return [NSData dataWithBytes:output length:outputLength];
    }
    
    - (nonnull NSData*) SwiftyRSASHA224 {
        unsigned int outputLength = CC_SHA224_DIGEST_LENGTH;
        unsigned char output[outputLength];
        
        CC_SHA224(self.bytes, (unsigned int) self.length, output);
        return [NSData dataWithBytes:output length:outputLength];
    }
    
    - (nonnull NSData*) SwiftyRSASHA256 {
        unsigned int outputLength = CC_SHA256_DIGEST_LENGTH;
        unsigned char output[outputLength];
        
        CC_SHA256(self.bytes, (unsigned int) self.length, output);
        return [NSData dataWithBytes:output length:outputLength];
    }
    
    - (nonnull NSData*) SwiftyRSASHA384 {
        unsigned int outputLength = CC_SHA384_DIGEST_LENGTH;
        unsigned char output[outputLength];
        
        CC_SHA384(self.bytes, (unsigned int) self.length, output);
        return [NSData dataWithBytes:output length:outputLength];
    }
    
    - (nonnull NSData*) SwiftyRSASHA512 {
        unsigned int outputLength = CC_SHA512_DIGEST_LENGTH;
        unsigned char output[outputLength];
        
        CC_SHA512(self.bytes, (unsigned int) self.length, output);
        return [NSData dataWithBytes:output length:outputLength];
    }
    
    @end
    


    3.SwiftyRSA.swift :

    import Foundation
    import Security
    
    
    public class SwiftyRSAError: NSError {
        init(message: String) {
            super.init(domain: "com.takescoop.SwiftyRSA", code: 500, userInfo: [
                NSLocalizedDescriptionKey: message
                ])
        }
        
        
        @available(*, unavailable)
        required public init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    /**
    Represents the result of a signature verification
    */
    
    @objc
    public class VerificationResult: NSObject, BooleanType {
        
        /// `true` if the signature was verified
        
        public let boolValue: Bool
        
        init(_ boolValue: Bool) {
            self.boolValue = boolValue
        }
    }
    
    @objc
    public class SwiftyRSA: NSObject {
        
        @objc public enum DigestType: Int {
            case SHA1
            case SHA224
            case SHA256
            case SHA384
            case SHA512
        }
        
        private var keyTags: [NSData] = []
        private static let defaultPadding: SecPadding = .PKCS1
        private static var defaultDigest: DigestType = .SHA1
        
        // MARK: - Public Shorthands
        
        public class func encryptString(str: String, publicKeyPEM: String, padding: SecPadding = defaultPadding) throws -> String {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromPEMString(publicKeyPEM)
            return try rsa.encryptString(str, publicKey: key, padding: padding)
        }
        
        public class func encryptString(str: String, publicKeyDER: NSData, padding: SecPadding = defaultPadding) throws -> String {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromDERData(publicKeyDER)
            return try rsa.encryptString(str, publicKey: key, padding: padding)
        }
        
        public class func decryptString(str: String, privateKeyPEM: String, padding: SecPadding = defaultPadding) throws -> String {
            let rsa = SwiftyRSA()
            let key = try rsa.privateKeyFromPEMString(privateKeyPEM)
            return try rsa.decryptString(str, privateKey: key, padding: padding)
        }
        
        public class func encryptData(data: NSData, publicKeyPEM: String, padding: SecPadding = defaultPadding) throws -> NSData {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromPEMString(publicKeyPEM)
            return try rsa.encryptData(data, publicKey: key, padding: padding)
        }
        
        public class func encryptData(data: NSData, publicKeyDER: NSData, padding: SecPadding = defaultPadding) throws -> NSData {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromDERData(publicKeyDER)
            return try rsa.encryptData(data, publicKey: key, padding: padding)
        }
        
        public class func decryptData(data: NSData, privateKeyPEM: String, padding: SecPadding = defaultPadding) throws -> NSData {
            let rsa = SwiftyRSA()
            let key = try rsa.privateKeyFromPEMString(privateKeyPEM)
            return try rsa.decryptData(data, privateKey: key, padding: padding)
        }
        
        /**
        Sign a `String` using a private key.  The supplied string will be hashed using the specified
        hashing function and the resulting digest will be signed.
        
        - parameter str: The `String` to be signed.
        - parameter privateKeyPEM: A `String` containing the private key for the signing operation in PEM format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: Base64 encoded signature for the hash of the string.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        public class func signString(str: String, privateKeyPEM: String, digestMethod: DigestType = defaultDigest) throws -> String {
            let rsa = SwiftyRSA()
            let key = try rsa.privateKeyFromPEMString(privateKeyPEM)
            return try rsa.signString(str, privateKey: key, digestMethod: digestMethod)
        }
        
        /**
        Sign an `NSData` block using a private key.  The supplied data will be hashed using the specified
        hashing function and the resulting digest will be signed.
        
        - parameter data: The `NSData` to be signed.
        - parameter privateKeyPEM: A `String` containing the private key for the signing operation in PEM format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: The signature for the hash of the string.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        public class func signData(data: NSData, privateKeyPEM: String, digestMethod: DigestType = defaultDigest) throws -> NSData {
            let rsa = SwiftyRSA()
            let key = try rsa.privateKeyFromPEMString(privateKeyPEM)
            return try rsa.signData(data, privateKey: key, digestMethod: digestMethod)
        }
        
        /**
        Verify a signature using a public key.  The supplied `String` will be hashed and the
        resulting digest will be verified against the supplied signature.
        
        - parameter str: The `String` to be verified.  This string will be hashed.
        - parameter signature: The BASE64 string representation of the signature to be verified.
        - parameter publicKeyPEM: A `String` containing the public key for the signing operation in PEM format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public class func verifySignatureString(str: String, signature: String, publicKeyPEM: String, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromPEMString(publicKeyPEM)
            return try rsa.verifySignatureString(str, signature: signature, publicKey: key, digestMethod: digestMethod)
        }
        
        /**
        Verify a signature using a public key.  The supplied `NSData` will be hashed  and the
        resulting digest will be verified against the supplied signature.
        
        - parameter data: The `NSData` to be verified.  This data will be hashed
        - parameter signature: The signature to be verified.
        - parameter publicKeyPEM: A `String` containing the public key for the signing operation in PEM format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public class func verifySignatureData(data: NSData, signature: NSData, publicKeyPEM: String, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromPEMString(publicKeyPEM)
            return try rsa.verifySignatureData(data, signatureData: signature, publicKey: key, digestMethod: digestMethod)
        }
        
        /**
        Verify a signature using a public key.  The supplied `String` will be hashed and the
        resulting digest will be verified against the supplied signature.
        
        - parameter str: The `String` to be verified.  This string will be hashed
        - parameter signature: The BASE64 string representation of the signature to be verified.
        - parameter publicKeyDER: The public key for the signing operation in DER format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public class func verifySignatureString(str: String, signature: String, publicKeyDER: NSData, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromDERData(publicKeyDER)
            return try rsa.verifySignatureString(str, signature: signature, publicKey: key, digestMethod: digestMethod)
        }
        
        /**
        Verify a signature using a public key.  The supplied `NSData` will be hashed and the
        resulting digest will be verified against the supplied signature.
        
        - parameter data: The `NSData` to be verified.  This data will be hashed
        - parameter signature: The signature to be verified.
        - parameter publicKeyDER: The public key for the signing operation in DER format
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public class func verifySignatureData(data: NSData, signature: NSData, publicKeyDER: NSData, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            let rsa = SwiftyRSA()
            let key = try rsa.publicKeyFromDERData(publicKeyDER)
            return try rsa.verifySignatureData(data, signatureData: signature, publicKey: key, digestMethod: digestMethod)
        }
        
        
        // MARK: - Public Advanced Methods
        
        public override init() {
            super.init()
        }
        
        public func publicKeyFromDERData(keyData: NSData) throws -> SecKeyRef {
            return try addKey(keyData, isPublic: true)
        }
        
        public func publicKeyFromPEMString(key: String) throws -> SecKeyRef {
            let data = try dataFromPEMKey(key)
            return try addKey(data, isPublic: true)
        }
        
        public func privateKeyFromPEMString(key: String) throws -> SecKeyRef {
            let data = try dataFromPEMKey(key)
            return try addKey(data, isPublic: false)
        }
        
        // Encrypts data with a RSA key
        public func encryptData(data: NSData, publicKey: SecKeyRef, padding: SecPadding) throws -> NSData {
            let blockSize = SecKeyGetBlockSize(publicKey)
            let maxChunkSize = blockSize - 11
            
            var decryptedDataAsArray = [UInt8](count: data.length / sizeof(UInt8), repeatedValue: 0)
            data.getBytes(&decryptedDataAsArray, length: data.length)
            
            var encryptedData = [UInt8](count: 0, repeatedValue: 0)
            var idx = 0
            while (idx < decryptedDataAsArray.count) {
                
                let idxEnd = min(idx + maxChunkSize, decryptedDataAsArray.count)
                let chunkData = [UInt8](decryptedDataAsArray[idx..<idxEnd])
                
                var encryptedDataBuffer = [UInt8](count: blockSize, repeatedValue: 0)
                var encryptedDataLength = blockSize
                
                let status = SecKeyEncrypt(publicKey, padding, chunkData, chunkData.count, &encryptedDataBuffer, &encryptedDataLength)
                
                guard status == noErr else {
                    throw SwiftyRSAError(message: "Couldn't encrypt chunk at index \(idx)")
                }
                
                encryptedData += encryptedDataBuffer
                
                idx += maxChunkSize
            }
            
            return NSData(bytes: encryptedData, length: encryptedData.count)
        }
        
        // Decrypt an encrypted data with a RSA key
        public func decryptData(encryptedData: NSData, privateKey: SecKeyRef, padding: SecPadding) throws -> NSData {
            let blockSize = SecKeyGetBlockSize(privateKey)
            
            var encryptedDataAsArray = [UInt8](count: encryptedData.length / sizeof(UInt8), repeatedValue: 0)
            encryptedData.getBytes(&encryptedDataAsArray, length: encryptedData.length)
            
            var decryptedData = [UInt8](count: 0, repeatedValue: 0)
            var idx = 0
            while (idx < encryptedDataAsArray.count) {
                
                let idxEnd = min(idx + blockSize, encryptedDataAsArray.count)
                let chunkData = [UInt8](encryptedDataAsArray[idx..<idxEnd])
                
                var decryptedDataBuffer = [UInt8](count: blockSize, repeatedValue: 0)
                var decryptedDataLength = blockSize
                
                let status = SecKeyDecrypt(privateKey, padding, chunkData, idxEnd-idx, &decryptedDataBuffer, &decryptedDataLength)
                guard status == noErr else {
                    throw SwiftyRSAError(message: "Couldn't decrypt chunk at index \(idx)")
                }
                
                decryptedData += [UInt8](decryptedDataBuffer[0..<decryptedDataLength])
                
                idx += blockSize
            }
            
            return NSData(bytes: decryptedData, length: decryptedData.count)
        }
        
        public func encryptString(str: String, publicKey: SecKeyRef, padding: SecPadding = defaultPadding) throws -> String {
            guard let data = str.dataUsingEncoding(NSUTF8StringEncoding) else {
                throw SwiftyRSAError(message: "Couldn't get UT8 data from provided string")
            }
            let encryptedData = try encryptData(data, publicKey: publicKey, padding: padding)
            return encryptedData.base64EncodedStringWithOptions([])
        }
        
        public func decryptString(str: String, privateKey: SecKeyRef, padding: SecPadding = defaultPadding) throws -> String {
            guard let data =  NSData(base64EncodedString: str, options: []) else {
                throw SwiftyRSAError(message: "Couldn't decode base 64 encoded string")
            }
            
            let decryptedData = try decryptData(data, privateKey: privateKey, padding: padding)
            
            guard let decryptedString = NSString(data: decryptedData, encoding: NSUTF8StringEncoding) else {
                throw SwiftyRSAError(message: "Couldn't convert decrypted data to UTF8 string")
            }
            
            return decryptedString as String
        }
        
        // Mark: - Digital signatures
        
        // Sign data with an RSA key
        
        /**
        Sign a `String` using a private key.  The supplied string will be hashed using the specified
        hashing method and the resulting hash will be signed.
        
        - parameter str: The `String` to be signed.
        - parameter privateKey: A `SecKeyRef` for the private key
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: Base64 encoded signature for the hash of the string.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        public func signString(str: String, privateKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> String {
            guard let data = str.dataUsingEncoding(NSUTF8StringEncoding) else {
                throw SwiftyRSAError(message: "Couldn't get UTF8 data from provided string")
            }
            let signature = try signData(data, privateKey: privateKey, digestMethod:digestMethod)
            return signature.base64EncodedStringWithOptions([])
        }
        
        /**
        Sign an `NSData` block using a private key.  The supplied data will be hashed using the specified
        hashing method and the resulting digest will be signed.
        
        - parameter data: The `NSData` to be signed.
        - parameter privateKey: A `SecKeyRef` for the private key
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: The signature for the  hash of the string.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        public func signData(data: NSData, privateKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> NSData {
            
            let (digest, padding) = self.digestForData(data, digestMethod: digestMethod)
            
            return try signDigest(digest, privateKey: privateKey,  padding: padding)
        }
        
        /**
        Sign an `NSData` block using a private key.  The supplied data must represent an SHA1 digest.
        
        - parameter digest: The `NSData` containing the SHA1 digest to be signed.
        - parameter privateKey: A `SecKeyRef` for the private key
        - returns: The signature for the SHA1 digest.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        @available(*, deprecated = 0.31, message = "Use signDigest() with digestMethod = .SHA1")
        public func signSHA1Digest(digest: NSData, privateKey: SecKeyRef) throws -> NSData {
            
            return try self.signDigest(digest, privateKey: privateKey, padding: .PKCS1SHA1)
            
        }
        
        /**
        Sign an `NSData` block using a private key.  The supplied data must represent a digest of the indicated type.
        
        - parameter digest: The `NSData` containing the SHA1 digest to be signed.
        - parameter privateKey: A `SecKeyRef` for the private key
        - parameter digestMethod: The digest type contained in `digest`
        - returns: The signature for the SHA1 digest.
        - throws: `SwiftyRSAError` if there is an error in the signing process
        */
        
        public func signDigest(digest: NSData, privateKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> NSData {
            
            let (_,padding) = self.digestForData(digest, digestMethod: digestMethod)
            
            return try self.signDigest(digest, privateKey: privateKey, padding: padding)
            
        }
        
        // Verify data with an RSA key
        
        /**
        Verify a signature using a public key.  The supplied `String` will be hashed using the specified
        hasing function and resulting digest will be verified against the supplied signature.
        
        - parameter str: The `String` to be verified.  This string will be hashed
        - parameter signature: The BASE64 string representation of the signature to be verified.
        - parameter publicKey: A `SecKeyRef` for the public key
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public func verifySignatureString(str: String, signature: String, publicKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            
            
            guard let data = str.dataUsingEncoding(NSUTF8StringEncoding) else {
                throw SwiftyRSAError(message: "Couldn't get UTF8 data from provided string")
            }
            
            guard let signatureData = NSData(base64EncodedString: signature, options: []) else {
                throw SwiftyRSAError(message: "Couldn't get signature data from provided base64 string")
            }
            
            return try verifySignatureData(data, signatureData: signatureData, publicKey: publicKey, digestMethod: digestMethod)
            
        }
        
        /**
        Verify a signature using a public key.  The supplied `NSData` will be hashed and the
        resulting digest will be verified against the supplied signature.
        
        - parameter data: The `NSData` to be verified.  This string will be hashed
        - parameter signatureData: The of the signature data to be verified.
        - parameter publicKey: A `SecKeyRef` for the public key
        - parameter digestMethod: The `DigestType` that indicates the hashing function
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public func verifySignatureData(data: NSData, signatureData: NSData, publicKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            
            let (digest, padding) = self.digestForData(data, digestMethod: digestMethod)
            
            return try verifySignatureData(digest, signature: signatureData, publicKey: publicKey, padding: padding)
            
        }
        
        /**
        Verify a signature using a public key.  The supplied `NSData` represents an SHA1 digest to be verified against the supplied signature.
        
        - parameter SHA1Data: The `NSData` containing the SHA1 digest to be verified.
        - parameter signature: The `NSData` containing the signature to be verified.
        - parameter publicKey: A `SecKeyRef` for the public key
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        @available(*, deprecated = 0.31, message = "Use verifySignature() with digestMethod = .SHA1")
        public func verifySHA1SignatureData(SHA1Data: NSData, signature: NSData, publicKey: SecKeyRef) throws -> VerificationResult {
            
            return try self.verifySignatureData(SHA1Data, signature: signature, publicKey: publicKey, padding: .PKCS1SHA1)
        }
        
        /**
        Verify a signature using a public key.  The supplied `NSData` represents a digest to be verified against the supplied signature.
        
        - parameter digestData: The `NSData` containing the  digest to be verified.
        - parameter signature: The `NSData` containing the signature to be verified.
        - parameter publicKey: A `SecKeyRef` for the public key
        - parameter digestMethod: The method used to create the digest in the `digest` parameter
        - returns: A `VerificationResult` that indicates whether the signature was valid or not
        - throws: `SwiftyRSAError` if there is an error in the verification process
        */
        
        public func verifySignatureData(digestData: NSData, signature: NSData, publicKey: SecKeyRef, digestMethod: DigestType = defaultDigest) throws -> VerificationResult {
            
            let (_,padding) = self.digestForData(digestData, digestMethod: digestMethod)
            
            return try self.verifySignatureData(digestData, signature: signature, publicKey: publicKey, padding: padding)
        }
        
        
        // MARK: - Private
        
        private func addKey(keyData: NSData, isPublic: Bool) throws -> SecKeyRef {
            
            var keyData = keyData
            
            // Strip key header if necessary
            if isPublic {
                try keyData = stripPublicKeyHeader(keyData)
            }
            
            let tag = NSUUID().UUIDString
            let tagData = NSData(bytes: tag, length: tag.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
            removeKeyWithTagData(tagData)
            
            // Add persistent version of the key to system keychain
            let persistKey = UnsafeMutablePointer<AnyObject?>(nil)
            let keyClass   = isPublic ? kSecAttrKeyClassPublic : kSecAttrKeyClassPrivate
            
            // Add persistent version of the key to system keychain
            let keyDict = NSMutableDictionary()
            keyDict.setObject(kSecClassKey,         forKey: kSecClass as! NSCopying)
            keyDict.setObject(tagData,              forKey: kSecAttrApplicationTag as! NSCopying)
            keyDict.setObject(kSecAttrKeyTypeRSA,   forKey: kSecAttrKeyType as! NSCopying)
            keyDict.setObject(keyData,              forKey: kSecValueData as! NSCopying)
            keyDict.setObject(keyClass,             forKey: kSecAttrKeyClass as! NSCopying)
            keyDict.setObject(NSNumber(bool: true), forKey: kSecReturnPersistentRef as! NSCopying)
            keyDict.setObject(kSecAttrAccessibleWhenUnlocked, forKey: kSecAttrAccessible as! NSCopying)
            
            var secStatus = SecItemAdd(keyDict as CFDictionary, persistKey)
            if secStatus != noErr && secStatus != errSecDuplicateItem {
                throw SwiftyRSAError(message: "Provided key couldn't be added to the keychain")
            }
            
            keyTags.append(tagData)
            
            // Now fetch the SecKeyRef version of the key
            var keyRef: AnyObject? = nil
            keyDict.removeObjectForKey(kSecValueData)
            keyDict.removeObjectForKey(kSecReturnPersistentRef)
            keyDict.setObject(NSNumber(bool: true), forKey: kSecReturnRef as! NSCopying)
            keyDict.setObject(kSecAttrKeyTypeRSA,   forKey: kSecAttrKeyType as! NSCopying)
            secStatus = SecItemCopyMatching(keyDict as CFDictionaryRef, &keyRef)
            
            guard let unwrappedKeyRef = keyRef else {
                throw SwiftyRSAError(message: "Couldn't get key reference from the keychain")
            }
            
            return unwrappedKeyRef as! SecKeyRef
        }
        
        private func dataFromPEMKey(key: String) throws -> NSData {
            
            let lines = key.componentsSeparatedByString("\n").filter { line in
                return !line.hasPrefix("-----BEGIN") && !line.hasPrefix("-----END")
            }
            
            guard lines.count != 0 else {
                throw SwiftyRSAError(message: "Couldn't get data from PEM key: no data available after stripping headers")
            }
            
            // Decode base64 key
            let base64EncodedKey = lines.joinWithSeparator("")
            let keyData = NSData(base64EncodedString: base64EncodedKey, options: .IgnoreUnknownCharacters)
            
            guard let unwrappedKeyData = keyData where unwrappedKeyData.length != 0 else {
                throw SwiftyRSAError(message: "Couldn't decode PEM key data (base64)")
            }
            
            return unwrappedKeyData
        }
        
        /**
        This method strips the x509 from a provided ASN.1 DER public key.
        If the key doesn't contain a header, the DER data is returned as is.
        
        Supported formats are:
        
        Headerless:
        SEQUENCE
        INTEGER (1024 or 2048 bit) -- modulo
        INTEGER -- public exponent
        
        With x509 header:
        SEQUENCE
        SEQUENCE
        OBJECT IDENTIFIER 1.2.840.113549.1.1.1
        NULL
        BIT STRING
        SEQUENCE
        INTEGER (1024 or 2048 bit) -- modulo
        INTEGER -- public exponent
        
        Example of headerless key:
        https://lapo.it/asn1js/#3082010A0282010100C1A0DFA367FBC2A5FD6ED5A071E02A4B0617E19C6B5AD11BB61192E78D212F10A7620084A3CED660894134D4E475BAD7786FA1D40878683FD1B7A1AD9C0542B7A666457A270159DAC40CE25B2EAE7CCD807D31AE725CA394F90FBB5C5BA500545B99C545A9FE08EFF00A5F23457633E1DB84ED5E908EF748A90F8DFCCAFF319CB0334705EA012AF15AA090D17A9330159C9AFC9275C610BB9B7C61317876DC7386C723885C100F774C19830F475AD1E9A9925F9CA9A69CE0181A214DF2EB75FD13E6A546B8C8ED699E33A8521242B7E42711066AEC22D25DD45D56F94D3170D6F2C25164D2DACED31C73963BA885ADCB706F40866B8266433ED5161DC50E4B3B0203010001
        
        Example of key with X509 header (notice the additional ASN.1 sequence):
        https://lapo.it/asn1js/#30819F300D06092A864886F70D010101050003818D0030818902818100D0674615A252ED3D75D2A3073A0A8A445F3188FD3BEB8BA8584F7299E391BDEC3427F287327414174997D147DD8CA62647427D73C9DA5504E0A3EED5274A1D50A1237D688486FADB8B82061675ABFA5E55B624095DB8790C6DBCAE83D6A8588C9A6635D7CF257ED1EDE18F04217D37908FD0CBB86B2C58D5F762E6207FF7B92D0203010001
        */
        private func stripPublicKeyHeader(keyData: NSData) throws -> NSData {
            let count = keyData.length / sizeof(CUnsignedChar)
            
            guard count > 0 else {
                throw SwiftyRSAError(message: "Provided public key is empty")
            }
            
            var byteArray = [UInt8](count: count, repeatedValue: 0)
            keyData.getBytes(&byteArray, length: keyData.length)
            
            var index = 0
            guard byteArray[index] == 0x30 else {
                throw SwiftyRSAError(message: "Provided key doesn't have a valid ASN.1 structure (first byte should be 0x30 == SEQUENCE)")
            }
            
            index += 1
            if byteArray[index] > 0x80 {
                index += Int(byteArray[index]) - 0x80 + 1
            }
            else {
                index += 1
            }
            
            // If current byte marks an integer (0x02), it means the key doesn't have a X509 header and just
            // contains its modulo & public exponent. In this case, we can just return the provided DER data as is.
            if Int(byteArray[index]) == 0x02 {
                return keyData
            }
            
            // Now that we've excluded the possibility of headerless key, we're looking for a valid X509 header sequence.
            // It should look like this:
            // 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00
            guard Int(byteArray[index]) == 0x30 else {
                throw SwiftyRSAError(message: "Provided key doesn't have a valid X509 header")
            }
            
            index += 15
            if byteArray[index] != 0x03 {
                throw SwiftyRSAError(message: "Invalid byte at index \(index - 1) (\(byteArray[index - 1])) for public key header")
            }
            
            index += 1
            if byteArray[index] > 0x80 {
                index += Int(byteArray[index]) - 0x80 + 1
            }
            else {
                index += 1
            }
            
            guard byteArray[index] == 0 else {
                throw SwiftyRSAError(message: "Invalid byte at index \(index - 1) (\(byteArray[index - 1])) for public key header")
            }
            
            index += 1
            
            let strippedKeyBytes = [UInt8](byteArray[index...keyData.length - 1])
            let data = NSData(bytes: strippedKeyBytes, length: keyData.length - index)
            
            return data
        }
        
        private func removeKeyWithTagData(tagData: NSData) {
            let publicKey = NSMutableDictionary()
            publicKey.setObject(kSecClassKey,       forKey: kSecClass as! NSCopying)
            publicKey.setObject(kSecAttrKeyTypeRSA, forKey: kSecAttrKeyType as! NSCopying)
            publicKey.setObject(tagData,            forKey: kSecAttrApplicationTag as! NSCopying)
            SecItemDelete(publicKey as CFDictionaryRef)
        }
        
        private func signDigest(digest: NSData, privateKey: SecKeyRef, padding: SecPadding) throws -> NSData {
            
            let blockSize = SecKeyGetBlockSize(privateKey)
            let maxChunkSize = blockSize - 11
            
            guard (digest.length / sizeof(UInt8) <= maxChunkSize) else {
                throw SwiftyRSAError(message: "data length exceeds \(maxChunkSize)")
            }
            
            var signDataAsArray = [UInt8](count: digest.length / sizeof(UInt8), repeatedValue: 0)
            digest.getBytes(&signDataAsArray, length: digest.length)
            
            var signatureData = [UInt8](count: blockSize, repeatedValue: 0)
            var signatureDataLength = blockSize
            
            let status = SecKeyRawSign(privateKey, padding, signDataAsArray, signDataAsArray.count, &signatureData, &signatureDataLength)
            
            
            guard status == noErr else {
                throw SwiftyRSAError(message: "Couldn't sign data \(status)")
            }
            
            
            return NSData(bytes: signatureData, length: signatureData.count)
        }
        
        private func verifySignatureData(SHAData: NSData, signature: NSData, publicKey: SecKeyRef, padding: SecPadding) throws -> VerificationResult {
            
            var verifyDataAsArray = [UInt8](count: SHAData.length / sizeof(UInt8), repeatedValue: 0)
            SHAData.getBytes(&verifyDataAsArray, length: SHAData.length)
            
            var signatureDataAsArray = [UInt8](count: signature.length / sizeof(UInt8), repeatedValue: 0)
            signature.getBytes(&signatureDataAsArray, length: signature.length)
            
            let status = SecKeyRawVerify(publicKey, padding, verifyDataAsArray, verifyDataAsArray.count, signatureDataAsArray, signatureDataAsArray.count)
            
            if (status == errSecSuccess) {
                return VerificationResult(true)
            } else if (status == -9809) {
                return VerificationResult(false)
            } else {
                throw SwiftyRSAError(message: "Couldn't verify signature - \(status)")
            }
        }
        //20161102
        private func digestForData(data: NSData, digestMethod: DigestType) -> (digest:NSData, padding:SecPadding) {
            
            var digest: NSData
            var padding: SecPadding
            
            switch digestMethod {
            case .SHA1:
                digest = data.SwiftyRSASHA1()
                padding = .PKCS1SHA1
            case .SHA224:
                digest = data.SwiftyRSASHA224()
                padding = .PKCS1SHA224
            case .SHA256:
                digest = data.SwiftyRSASHA256()
                padding = .PKCS1SHA256
            case .SHA384:
                digest = data.SwiftyRSASHA384()
                padding = .PKCS1SHA384
            case .SHA512:
                digest = data.SwiftyRSASHA512()
                padding = .PKCS1SHA512
            }
            
            return (digest,padding)
        }
        
        deinit {
            for tagData in keyTags {
                removeKeyWithTagData(tagData)
            }
        }
    }




    展开全文
  • Swift中的 RSA Sign

    2018-08-20 14:45:15
    实现方式为使用了Github开源库SecrecySwift,但此项目有一段时间没有人维护,按照readme中的集成方式,在新的Xcode9.4 or Swift4中不能在真机中正常运行。 修复方式如下: Xcode 9.3, Swift 4项目, 引入此项目,按...

    项目中,使用了Https+RSA Sign的认证方式

    实现方式为使用了Github开源库SecrecySwift,但此项目有一段时间没有人维护,按照readme中的集成方式,在新的Xcode9.4 or Swift4中不能在真机中正常运行。

    修复方式如下:

    Xcode 9.3, Swift 4项目, 引入此项目,按readme中的直接部署源码的方式已无法正常运行。

    解决办法:

    1.删除CommonCrypto文件夹,在项目 Targets 的 Build Settings 中 Import Paths 中删除 CommonCrypto, 在 Library Search Path 中删除 /usr/lib/system

    2.在自己项目的xxx-Bridging-Header.h文件中,#import <CommonCrypto/CommonCrypto.h>

    3.删除此项目中出现的import CommonCrypto,成功在真机上运行。

     

    在发现此修复方式的过程中,尝试自己手写一套RSA Sign,参考如下代码:

            let ts = Date().timeIntervalSince1970 * 1000000
            let signString = "xxx&ts=\(Int64(ts))"
            let pathPrivate = Bundle.main.path(forResource: "pri", ofType: "p12")
            let pathPublic = Bundle.main.path(forResource: "pub", ofType: "der")
    
            let privateUrl = URL(fileURLWithPath: pathPrivate!)
            let privateData = try! Data(contentsOf: privateUrl)
            let privatePwd = "xxx"
            let options = [kSecImportExportPassphrase as String: privatePwd]
            var rawItems: CFArray?
            let status = SecPKCS12Import(privateData as CFData, options as CFDictionary, &rawItems)
            guard status == errSecSuccess else { return }
            let items = rawItems! as! Array<Dictionary<String, Any>>
            let firstItem = items[0]
            let identity = firstItem[kSecImportItemIdentity as String] as! SecIdentity?
    
            var privateKey: SecKey?
            let status1 = SecIdentityCopyPrivateKey(identity!, &privateKey)
            guard status1 == errSecSuccess else { return }
    
            var signedStr = ""
            if #available(iOS 10.0, *) { // iOS10以后,系统原生实现方式
                let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA1
                guard SecKeyIsAlgorithmSupported(privateKey!, .sign, algorithm) else {
                    return
                }
                var error: Unmanaged<CFError>?
                guard let signature = SecKeyCreateSignature(privateKey!,
                                                            algorithm,
                                                            signString.data(using: .utf8)! as CFData,
                                                            &error) as Data? else {
                                                                return
                }
                signedStr = signature.base64EncodedString()
            } else { // 老的实现方式,使用了SecrecySwift中的两个文件Digest.swift和SecrecyExtension.swift,在自己项目的xxx-Bridging-Header.h文件中,#import <CommonCrypto/CommonCrypto.h>,删除这两个文件中中出现的import CommonCrypto
                let signData = signString.data(using: .utf8)!
                let digestInputData = signData.digestData(.sha1)
                guard digestInputData.count > 0 && digestInputData.count < SecKeyGetBlockSize(privateKey!) - 11  else {
                    return
                }
                let key_size = SecKeyGetBlockSize(privateKey!)
                var sign_bytes = [UInt8](repeating: 0, count: key_size)
                var sign_size : Int = key_size
                let result = SecKeyRawSign(privateKey!, SecPadding.PKCS1SHA1, digestInputData.arrayOfBytes(), digestInputData.count, &sign_bytes, &sign_size)
                guard result == errSecSuccess else {
                    return
                }
                let resultData = Data(bytes: UnsafePointer<UInt8>(sign_bytes), count: sign_size)
                signedStr = resultData.base64EncodedString()
            }

    展开全文
  • Swift 实现的 RSA, AES 加密解密工具类.zip,rsa公钥/私钥生成,rsa,aes加密/解密,rsa sign/verify in swift with commoncrypto in ios and os x
  • 开源框架RSA_Swift

    2019-07-23 09:57:57
    RSA_Swift RSA_Swift是一款轻量级的Swift版本的框架,框架功能包括:RSA加密/解密字符串、RSA加密/解密Data、字符串的MD5、文件的MD5值的获取。 写RSA_Swift初衷? github上Swift版本的RSA加密/解密框架也有,但...

    RSA_Swift

    RSA_Swift 是一款轻量级的 Swift 版本的框架,框架功能包括:RSA 加密/解密字符串、RSA 加密/解密 Data、字符串的 MD5、文件的 MD5 值的获取。

    写 RSA_Swift 初衷?

    github 上 Swift 版本的 RSA 加密/解密框架也有,但最近使用的几个,总是会出现这样或那样的问题,所以就写了这个框架,附带的加上比较常见的功能:字符串的 MD5、文件的 MD5 值的获取。

    对于文件的 MD5 值的获取,是将文件分块读出并且计算 MD5 值的方法,有别于文件一次性读出并且计算 MD5 值的方法。

    Example

    To run the example project, clone the repo, and run pod install from the Example directory first.

    Installation

    RSA_Swift is available through CocoaPods. To install
    it, simply add the following line to your Podfile:

    pod 'RSA_Swift'

     

    使用姿势

    rsa 加密字符串和解密字符串

    /// 注:rsa 加密 Data 和解密 Data 方法使用与`rsa 加密字符串和解密字符串`类似,这里就不写示例代码了

    let filePath = Bundle.main.path(forResource: "public_key", ofType: "der")

            

    let encryptString = "abcdefg"

    print("要加密的字符串:\(encryptString)")

            

    /// Encrypt

    RSA.rsaEncrypt(filePath, encryptString) { (encryptedString) in

        print("加密后的字符串:\(encryptedString ?? "")")

                

        let filePath1 = Bundle.main.path(forResource: "private_key.p12", ofType: nil)

        /// Decrypt

        RSA.rsaDecrypt(filePath1, "ios", encryptedString, { (decryptedString) in

            print("解密后的字符串:\(decryptedString ?? "")")

        })

    }

     

    获取文件的 MD5 值

    guard let filePath = Bundle.main.path(forResource: "test_file_md5", ofType: "png")

            else {

        return

    }

    print("文件的 MD5 值:\(filePath.md5_File() ?? "")")

     

    字符串的 MD5

    let str = "字符串的MD5"

    print("字符串的MD5:\(str.md5())")

    License

    RSA_Swift is available under the MIT license. See the LICENSE file for more info.

    Author

    如果你有什么建议,可以关注我的公众号:iOS开发者进阶,直接留言,留言必回。

     

    更多文章

    iOS SKStoreProductViewController的应用
    CocoaPods开源库的搭建
    CocoaPods搭建私有库
    CocoaPods搭建私有库遇到问题
    CocoaPods私有库的升级维护
    SKStoreReviewController之程序内评价
    App应用程序图标的动态更换
    开源框架 MGJRouter_Swift
    iOS的MVP设计模式
    iOS插件化
    iOS FMDB的使用
    Swift之ReactiveSwift
    OC之ReactiveCocoa
    OC之ReactiveCocoa进阶
    iOS 性能考虑

    转载于:https://www.cnblogs.com/MrXie821385843/p/10364686.html

    展开全文
  • SwiftyRSA, 在Swift中,RSA public/private 密钥加密 SwiftyRSA Swift中的 public 密钥RSA加密。 在将驱动程序编号提交到之前,在 Scoop iOS应用程序中使用SwiftyRSA来加密驱动程序许可证编号。安装 Swift 3.2/4. 0
  • 开源框架 RSA_Swift

    2019-02-12 11:54:59
    RSA_Swift 是一款轻量级的 Swift 版本的框架,框架功能包括:RSA 加密/解密字符串、RSA 加密/解密 Data、字符串的 MD5、文件的 MD5 值的获取。 写 RSA_Swift 初衷? github 上 Swift 版本的 RSA 加密/解密框架也有,...

    RSA_Swift

    RSA_Swift 是一款轻量级的 Swift 版本的框架,框架功能包括:RSA 加密/解密字符串、RSA 加密/解密 Data、字符串的 MD5、文件的 MD5 值的获取。

    RSA_Swift 初衷?

    githubSwift 版本的 RSA 加密/解密框架也有,但最近使用的几个,总是会出现这样或那样的问题,所以就写了这个框架,附带的加上比较常见的功能:字符串的 MD5、文件的 MD5 值的获取。

    对于文件的 MD5 值的获取,是将文件分块读出并且计算 MD5 值的方法,有别于文件一次性读出并且计算 MD5 值的方法。

    Example

    To run the example project, clone the repo, and run pod install from the Example directory first.

    Installation

    RSA_Swift is available through CocoaPods. To install
    it, simply add the following line to your Podfile:

    pod 'RSA_Swift'
    

    使用姿势

    rsa 加密字符串和解密字符串

    /// 注:rsa 加密 Data 和解密 Data 方法使用与`rsa 加密字符串和解密字符串`类似,这里就不写示例代码了
    let filePath = Bundle.main.path(forResource: "public_key", ofType: "der")
            
    let encryptString = "abcdefg"
    print("要加密的字符串:\(encryptString)")
            
    /// Encrypt
    RSA.rsaEncrypt(filePath, encryptString) { (encryptedString) in
        print("加密后的字符串:\(encryptedString ?? "")")
                
        let filePath1 = Bundle.main.path(forResource: "private_key.p12", ofType: nil)
        /// Decrypt
        RSA.rsaDecrypt(filePath1, "ios", encryptedString, { (decryptedString) in
            print("解密后的字符串:\(decryptedString ?? "")")
        })
    }
    

    获取文件的 MD5

    guard let filePath = Bundle.main.path(forResource: "test_file_md5", ofType: "png")
            else {
        return
    }
    print("文件的 MD5 值:\(filePath.md5_File() ?? "")")
    

    字符串的 MD5

    let str = "字符串的MD5"
    print("字符串的MD5:\(str.md5())")
    

    License

    RSA_Swift is available under the MIT license. See the LICENSE file for more info.

    Author

    如果你有什么建议,可以关注我的公众号:iOS开发者进阶,直接留言,留言必回。

    更多文章

    iOS SKStoreProductViewController的应用
    CocoaPods开源库的搭建
    CocoaPods搭建私有库
    CocoaPods搭建私有库遇到问题
    CocoaPods私有库的升级维护
    SKStoreReviewController之程序内评价
    App应用程序图标的动态更换
    开源框架 MGJRouter_Swift
    iOS的MVP设计模式
    iOS插件化
    iOS FMDB的使用
    Swift之ReactiveSwift
    OC之ReactiveCocoa
    OC之ReactiveCocoa进阶
    iOS 性能考虑

    展开全文
  • 基于CommonCrypto开发的RSA,AES加密/解密,RSA签名/验证
  • 最近在公司项目中被要求使用RSA加密,且要求是全程加解密,期间也是踩了很多的坑,在此做个记录也算给要使用的朋友一点帮助.注意,具体的RSA加密算法内容并不在此文的讨论范围之内.本文更多聚焦于使用部分. 我当前的使用...
  • swift-RSA加密解密

    2020-03-12 16:37:24
    RSA,非对称密码加密算法,需要一对密钥,使用其中一个加密,使用另一个解密。在进行RSA加密通讯时,把公钥放到客户端,把私钥留到服务器。
  • VKRSA-迄今最好的iOS原生RSA库,性能高,使用简单
  • RSA是一种比较常用的非对称加密算法,其原理是基于大整数因数分解的计算安全,这里不做介绍。非对称加密的好处在于其密码分为公钥和私钥两部分,你可以随意分发你的公钥,让用户用来加密数据;等上传到服务器端后再...
  • iOS——RSA加密方法

    2015-12-03 16:49:00
    iOS上并没有直接的RSA加密API。但是iOS提供了x509的API,而x509是支持RSA加密的。因此,我们可以通过制作自签名的x509证书(由于对安全性要求不高,我们并不需要使用CA认证的证书),再调用x509的相关API来进行加密...
  • iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于解密. 首先需要先生成这些文件,然后再将文件...
  • 工作中用到了非对称加密:RSA加解密及签名验证,根据查到的信息及工作中的问题总结,现在整理如下: 1. 准备好公钥和私钥,使用openssl工具生成RSA公钥和私钥对 1)生成RSA私钥: genrsa -out rsa_private_key....
  • 在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于解密. 首先需要先生成这些文件,然后再将文件...
  • SM2算法和RSA算法简介

    2019-08-20 00:38:38
    SM2算法和RSA算法都是公钥密码算法,SM2算法是一种更先进安全的算法,在安全性能、速度性能等方面都优于RSA算法,在我国商用密码体系中被用来替换RSA... SM2算法和RSA算法简介 RSA公钥加密算法是美国计算机学家R...
  • 对于iOS生成RSA密钥对来说,有两种选择,一种是通过系统原生的方法来生成,另一种是借助第三方库比如openssl。 iOS 原生生成密钥对(方法一) 系统提供了一系列关于RSA加解密和签名验签的方法,同时也提供了生成...
  • 已知RSA私钥各数据域,生成PEM文件。
  • 本文 字数:1619 密钥位数:1024。 密钥格式:PKCS#8。... 存在: 1、原RSA公私密钥对,转16进制公私密钥。2、自动生成16进制密钥对。3、使用16进制私钥签名。4、使用16进制公钥验证。5...
1 2 3 4 5 ... 20
收藏数 1,616
精华内容 646
关键字:

2048 rsa swift