RSA public/private key generation, RSA, AES encryption/decryption, RSA sign/verify in Swift with CommonCrypto in iOS and OS X

Overview

Carthage compatible

SwCrypt

Create public and private RSA keys in DER format

let (privateKey, publicKey) = try! CC.RSA.generateKeyPair(2048)

Convert them to PEM format

let privateKeyPEM = try SwKeyConvert.PrivateKey.derToPKCS1PEM(privateKey)
let publicKeyPEM = SwKeyConvert.PublicKey.derToPKCS8PEM(publicKey)

Or read them from strings with PEM data

let privateKeyDER = SwKeyConvert.PrivateKey.pemToPKCS1DER(privateKeyPEM)
let publicKeyDER = SwKeyConvert.PublicKey.pemToPKCS1DER(publicKeyPEM)

Or encrypt, decrypt the private key (OpenSSL compatible)

try SwKeyConvert.PrivateKey.encryptPEM(privateKeyPEM, passphrase: "longpassword", mode: .aes256CBC)
try SwKeyConvert.PrivateKey.decryptPEM(privEncrypted, passphrase: "longpassword")

Get public key from private keys in DER format

let publicKeyDER = try? CC.RSA.getPublicKeyFromPrivateKey(privateKeyDER!)

Encrypt, decrypt data with RSA

try CC.RSA.encrypt(data, derKey: publicKey, tag: tag, padding: .oaep, digest: .sha1)
try CC.RSA.decrypt(data, derKey: privateKey, tag: tag, padding: .oaep, digest: .sha1)

Sign, verify data with RSA

let sign = try? CC.RSA.sign(testMessage, derKey: privKey, padding: .pss, 
 digest: .sha256, saltLen: 16)
let verified = try? CC.RSA.verify(testMessage, derKey: pubKey, padding: .pss,
 digest: .sha256, saltLen: 16, signedData: sign!)

Elliptic curve functions

let keys = try? CC.EC.generateKeyPair(384)
let signed = try? CC.EC.signHash(keys!.0, hash: hash)
let verified = try? CC.EC.verifyHash(keys!.1, hash: hash, signedData: signed!)

let shared = try? CC.EC.computeSharedSecret(keys!.0, publicKey: partnerPubKey)

let privComponents = try? CC.EC.getPrivateKeyComponents(keys!.0)
let pubComponents = try? CC.EC.getPublicKeyComponents(keys!.1)

let pubKey = try? CC.EC.createFromData(keySize, x, y)
let pubKey = try? CC.EC.getPublicKeyFromPrivateKey(keys!.0)

Diffie-Hellman functions

let dh = try CC.DH.DH(dhParam: .rfc3526Group5)
let myPubKey = try dh.generateKey()
let commonKey = try dh.computeKey(partnerPubKey!)

Encrypt, decrypt data with symmetric ciphers

try CC.crypt(.encrypt, blockMode: .cbc, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: iv)
try CC.crypt(.decrypt, blockMode: .cfb, algorithm: .aes, padding: .pkcs7Padding, data: data, key: aesKey, iv: iv)

Encrypt, decrypt data with symmetric authenticating ciphers

try CC.cryptAuth(.encrypt, blockMode: .gcm, algorithm: .aes, data: data, aData: aData, key: aesKey, iv: iv, tagLength: tagLength)
try CC.cryptAuth(.decrypt, blockMode: .ccm, algorithm: .aes, data: data, aData: aData, key: aesKey, iv: iv, tagLength: tagLength)

Digest functions

CC.digest(data, alg: .md5)
CC.digest(data, alg: .sha256)
CC.digest(data, alg: .sha512)

HMAC function

CC.HMAC(data, alg: .sha512, key: key)

CMAC function

CC.CMAC.AESCMAC(input, key: key)

CRC function

let output = try? CC.CRC.crc(input, mode: .crc32)

KeyDerivation

CC.KeyDerivation.PBKDF2(password, salt: salt, prf: .sha256, rounds: 4096)

Symmetric Key Wrapping

try CC.KeyWrap.SymmetricKeyWrap(CC.KeyWrap.rfc3394IV, kek: kek, rawKey: rawKey)
try CC.KeyWrap.SymmetricKeyUnwrap(CC.KeyWrap.rfc3394IV, kek: kek, wrappedKey: wrappedKey)

Upsert, get, delete keys from KeyStore

try SwKeyStore.upsertKey(privateKeyPEM, keyTag: "priv", options: [kSecAttrAccessible:kSecAttrAccessibleWhenUnlockedThisDeviceOnly])
try SwKeyStore.getKey("priv")
try SwKeyStore.delKey("priv")

Check availability

SwCrypt uses dlopen and dlsym to load the CommonCrypto's functions, because not all of them are available in public header files. You have to check the availability before using them.

let digestAvailable : Bool = CC.digestAvailable()
let ramdomAvailable : Bool = CC.randomAvailable(()
let hmacAvailable : Bool = CC.hmacAvailable()
let cryptorAvailable : Bool = CC.cryptorAvailable
let keyDerivationAvailable : Bool = CC.KeyDerivation.available()
let keyWrapAvailable : Bool = CC.KeyWrap.available()
let rsaAvailable : Bool = CC.RSA.available()
let dhAvailable : Bool = CC.DH.available()
let ecAvailable : Bool = CC.EC.available()
let crcAvailable : Bool = CC.CRC.available()
let cmacAvailable : Bool = CC.CMAC.available()
let gcmAvailable : Bool = CC.GCM.available()
let ccmAvailable : Bool = CC.CCM.available()

or all in one turn:
let ccAvailable : Bool = CC.available()

Install

Just copy SwCrypt.swift to your project or use the Carthage dependency manager.

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. To install SwCrypt with CocoaPods:

  1. Make sure CocoaPods is installed.

  2. Update your Podfile to include the following:

    pod 'SwCrypt'
  3. Run pod install.

Swift Package Manager

SPM is built into new versions of Xcode. To install SwCrypt with SPM:

  1. Open your project in Xcode

  2. Click "File" -> "Swift Packages" -> "Add Package Dependency..."

  3. Paste the following URL: https://github.com/soyersoyer/SwCrypt

  4. Click "Next" -> "Next" -> "Finish"

Inspired from

License

This project is copyrighted under the MIT license.

Comments
  • Private key decrypt

    Private key decrypt

    Hi there,

    Do you know if iOS supports Public Key decryption?

    My use case needs me to encrypt some data with the private key, and decrypt it with the public key. The opposite of normal operation

    All the best!

    Johnny

    opened by johnnytshi 6
  • Import secp256k1 key

    Import secp256k1 key

    I'm trying this:

    let privateKey = "my-own-secp256k1-key-in-hex".dataFromHexadecimalString()
    let publicKey = "my-own-secp256k1-key-in-hex".dataFromHexadecimalString()
    

    But then I get a CC.CCError.memoryFailure with:

    let shared = try CC.EC.computeSharedSecret(privateKey, publicKey: publicKey)
    

    It doesn't happen when I import keys that have been generated with:

    let pair = try! CC.EC.generateKeyPair(256)
    let privateKey = pair.0.hex.dataFromHexadecimalString()
    let publicKey = pair.1.hex.dataFromHexadecimalString()
    let shared = try CC.EC.computeSharedSecret(privateKey, publicKey: publicKey)
    

    Instead of use CC.EC.generateKeyPair to get a keypair.

    • How can I import my own keypair? Is it supported?
    • What kind of EC keys are generated by default?
    opened by rseibane 6
  • Migrate to Swift 3.0

    Migrate to Swift 3.0

    Tests pass, except testUpsert and testDel. They fail on my machine: function SecItemAdd inside of SwKeyStore.upsertKey method returns status -34018. This happens before and after migration.

    opened by Nodepad 5
  • Maintainer needed

    Maintainer needed

    I don't have a Swift5, Xcode 10.2, OS X 10.14 compatible Mac, and I don't want to buy one only for this project.

    If you want to be a SwCrypt maintainer, please apply here.

    Responsibilities:

    • Review, test, accept pull requests
    • Release new versions, push them to cocoapods
    • If you want, you can write better documentation or you can add new features.

    Rules:

    • My GitHub account (@soyersoyer) should continue to be one of the owners of the project, but you will have full control over its future direction.
    opened by soyersoyer 4
  • AES key derivation is vulnerable to brute force attack

    AES key derivation is vulnerable to brute force attack

    The getAES128Key and getAES256Key methods are prone to brute-force attacks. Basically the key is computed as MD5(password + iv[0..7]). Given that the IV is a public info, the implementation can be reduced to MD5(password).

    MD5 is a very fast hashing function and is also vulnerable to collisions. This means that an attacker can compute hashes fast and also needs to search a smaller space.

    But even if the IV was not public, or if another hashing function would have been used (e.g. SHA2) the issue remains.

    The key derivation should be based on a password based key derivation function such as bcrypt or PBKDF2 (with high number of iterations).

    opened by pmilosev 4
  • RSA decrypt failure on iOS 8.1,please help

    RSA decrypt failure on iOS 8.1,please help

    Xcode: 9.3.1 Code:

    let data = "Hello Test".data(using: .utf8)!
    let (privateKey, publicKey) = try! CC.RSA.generateKeyPair(1024)
    // encrypt
    let encrypted = try! CC.RSA.encrypt(data, derKey: publicKey, tag: Data(), padding: .pkcs1, digest: .none)
    // decrypt
    do {
        let (decrypted,_) = try CC.RSA.decrypt(encrypted, derKey: privateKey, tag: Data(), padding: .pkcs1, digest: .none)
        print("decrypted:\(String(data:decrypted, encoding:.utf8)!)")
    }catch{
        print("decrypt fail")
    }
    
    

    decypt failure on Simulator:iPhone 5s 8.1,but success on Simulator: iPhone SE 11.3.

    CCCryptorStatus 
    CCRSACryptorDecrypt(
        CCRSACryptorRef privateKey, 
        CCAsymetricPadding padding, 
        const void *cipherText, 
        size_t cipherTextLen,
        void *plainText, 
        size_t *plainTextLen, 
        const void *tagData, 
        size_t tagDataLen, 
        CCDigestAlgorithm digestType)
    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
    

    It should be support iOS 5.0 and upper,But why decrypt failure on iOS 8.1?

    opened by dearwayne 4
  • How to  use method crypt(_:algorithm:data:key:iv:aData:tagLength:) for GCM? Gettingg error  [crypt(_:algorithm:data:key:iv:aData:tagLength:)] AppName.CC.CCError: paramError (-4300)

    How to use method crypt(_:algorithm:data:key:iv:aData:tagLength:) for GCM? Gettingg error [crypt(_:algorithm:data:key:iv:aData:tagLength:)] AppName.CC.CCError: paramError (-4300)

    Hi, I am using SwCrypt to implement GCM in my app. Below is the list of Parameter values I pass: opMode: .encrypt algorithm: .aes data: stringToEncrypt.data(using: .utf8)! key: keyString.data(using: .utf8)! iv: Random data of length 12 bytes aData: Random data of length 20 bytes (I'm not sure what this parameter is for) tagLength: 128

    I get the error [crypt(_:algorithm:data:key:iv:aData:tagLength:)] AppName.CC.CCError: paramError (-4300) I am unable to understand which parameter I am passing with wrong value

    opened by yogeshpadekar 4
  • Incorrect documentation on sign/verify?

    Incorrect documentation on sign/verify?

    Hey there,

    I've been using your swcrypt code in my app. Its very useful, so thank you very much. Its the only one that seems to include both pub key and symmetric algs together, without forcing me to use the keychain (like Heimdall does).

    However I was signing some data and found that the signature kept failing.

    Your doc says:

            let sign = try? CC.RSA.sign(testMessage, derKey: privKey, padding: .pss,  digest: .sha256, saltLen: 16)
    
             let verified = try? CC.RSA.verify(testMessage, derKey: pubKey, padding: .pss, digest: .sha256, saltLen: 16, signedData: sign!)
    
    

    which kind of implies that you pass the message data in to the sign and verify function. But I found it fails with more than about 100 bytes. Looking at your code for sign, the first parameter is actually:

            func sign(hash: NSData, derKey: NSData...
    
    

    It seems that the code is actually used to sign a hash rather than to sign raw data. Do your sample code probably should be something like this:(from my unit tests)

            let data = randomLargeData(10240)
    
            let hash = CC.digest(data, alg: .sha256)
    
            let sign = try? CC.RSA.sign(hash, derKey: privateKey, padding: .pkcs1,
                                        digest: .sha256)
    
            XCTAssertNotNil(sign, "Failed to sign")
    
            let verified = try? CC.RSA.verify(hash, derKey: publicKey, padding: .pkcs1, digest: .sha256, signedData: sign!)
    
            XCTAssertNotNil(verified, "Failed to calculate verification")
    
            XCTAssertTrue(verified!, "Failed to verify")
    
    

    This raises a question... why are we passing a digest name to the signing function? Is it required? The call to CCRSACryptorSign does seem to require it, but why? Does the digest passed in to sign() need to be the same as the digest used to hash the message?

    Also... note that your doc indicates "padding: .pss". That doesn't exist. lastly the saltLen parameter is no longer used.

    Again... thanks for the library.

    opened by tussock 4
  • Added SPM Support

    Added SPM Support

    • Added Package.swift
    • Updated README.md with SPM instructions
    • Updated .gitignore for swiftpm folder

    A new release would need to be created for SPM to see the manifest. Or just change my instructions in the readme to have them select the master branch when importing package.

    opened by mattmaddux 2
  • Swift 4.1 compile warnings

    Swift 4.1 compile warnings

    since Apple just formally released Swift 4.1, I have found this library has some compile warnings. SwCrypt.swift:742:18: Overlapping accesses to 'result', but modification requires exclusive access; consider copying to a local variable

    opened by chenyunguiMilook 2
  • How to use

    How to use

    Hello, everyone! Can you please help me to use SwCrypt?

    The task is to:

    1. Generate public and private keys
    2. Covert them to String format
    3. Encrypt some other string with a public key and receive another string as result of encryption
    4. Decrypt string received at the previous step with the private key

    To be honest, I'm new in cryptography and know a little about it's principles. Are actions mentioned above possible?

    I've read all the issues and still can't get how to use the library.

    1. I've generated public and private keys with. let (privateKey, publicKey) = try! CC.RSA.generateKeyPair(512) let privKeyStr = privateKey.base64EncodedString() let pubKeyStr = publicKey.base64EncodedString()

    2. I have a string which i want to encode and than decode let testString: String = "Test string"

    3. Trying to encode it: let testStringData = testString.data(using: .utf8)! let pubKeyData = pubKeyStr.data(using: .utf8)! let tagStr = "L" //still can't get what should I use there let tag = tagStr.data(using: .utf8)! let encryptedData = try! CC.RSA.encrypt(testStringData, derKey: pubKeyData, tag: tag, padding: .oaep, digest: .sha1)

    4. Get an error:

    CCError: decodeError (-4304)

    Can you please help me to use the library? Thanks!

    opened by jookovjook 2
  • Support for converting DER key pair in SecKey format

    Support for converting DER key pair in SecKey format

    I am using an external library that expects RSA based private/public key pair in SecKey format. I couldn't find a way to convert DER based key pair in SecKey format properly. Any help would be highly appreciated?

    opened by rohit3d2003 0
  • SwCrypt crashing on ref = CCDHCreate!(kCCDHRFC3526Group5!)

    SwCrypt crashing on ref = CCDHCreate!(kCCDHRFC3526Group5!)

    Application using SwCrypt crashing on ref = CCDHCreate!(kCCDHRFC3526Group5!)

    In the following Code "fileprivate static let kCCDHRFC3526Group5M: kCCDHRFC3526Group5TM? = getFunc(dl!, f: "kCCDHRFC3526Group5") fileprivate static let kCCDHRFC3526Group5 = kCCDHRFC3526Group5M?.pointee"

    kCCDHRFC3526Group5M value is nil on iPadOS 15.4 and 15.4.1 value is correctly calculated in iPadOS 14.x

    opened by BiraSha 0
  • not working when test with web

    not working when test with web

    hi, after generate keypair, i test with this website https://www.devglan.com/online-tools/rsa-encryption-decryption, it's success encrypt but fail to decrypt. You can see image here Ảnh chụp Màn hình 2021-12-07 lúc 20 50 44

    if using keypair from this website, it's work normally, can u explain why it's not working?

    opened by fukemy 0
  • Add / strip header to / from public PEM

    Add / strip header to / from public PEM

    String representation of Android RSA keys does not make use of standard PEM headers. In order to simplify export / import of public keys to / from Android, PEM headers should be made optional. A first step is opening up the add / strip header functions.

    opened by dbtech 0
Releases(5.1.4)
Owner
soyer
soyer
CCCryptor (AES encryption) wrappers for iOS and Mac in Swift. -- For ObjC, see RNCryptor/RNCryptor-objc

RNCryptor Cross-language AES Encryptor/Decryptor data format. The primary targets are Swift and Objective-C, but implementations are available in C, C

null 3.3k Jan 7, 2023
Util for generation RSA keys on your client and save to keychain or convert into Data 🔑 🔐

RSASwiftGenerator ?? ?? To run the example project, clone the repo, and run pod install from the Example directory first. Requirements ⚠️ SWIFT 4 XCod

null 21 Apr 30, 2022
A simple and opinionated AES encrypt / decrypt Objective-C class that just works.

AESCrypt-ObjC - Simple AES encryption / decryption for iOS and OS X AESCrypt is a simple to use, opinionated AES encryption / decryption Objective-C c

Gurpartap Singh 782 Oct 12, 2022
Read my answer here Importing CommonCrypto in a Swift framework

Read my answer here Importing CommonCrypto in a Swift framework

Khoa 281 Sep 17, 2022
Elegant Swift interface to access the CommonCrypto routines

SCrypto [Overview • Requirements • Installation • Usage • Alternatives • Licence] Overview SCrypto provides neat Swift interface to access the CommonC

Max 39 Mar 31, 2022
An easy way for hashing and encryption.

CatCrypto include a series of hashing and encryption functions and more functions in progress! CatCrypto also contains Swift bindings of Argon2, the p

Kcat 62 Sep 27, 2022
Enigma encryption in Swift

?????????????????? ?????????? // Will create an Enigma with an empty plugboard, rotors I, II, III and reflector B (wide). let enigma = Enigma() // Wil

Joakim Gyllström 113 Dec 16, 2022
Safe and easy to use crypto for iOS and macOS

Swift-Sodium Swift-Sodium provides a safe and easy to use interface to perform common cryptographic operations on macOS, iOS, tvOS and watchOS. It lev

Frank Denis 483 Jan 5, 2023
A KeePass/Password Safe Client for iOS and OS X

Strongbox A Personal Password Manager for iOS & OSX that can be found on the Apple App Store here: https://apps.apple.com/app/strongbox-password-safe/

Strongbox 976 Jan 3, 2023
A tiny and easy to use Swift class to encrypt strings using HMAC algorithms.

#Sweet HMAC SweetHMAC is a tiny and easy to use Swift class to encrypt strings using HMAC algorithms. A special thanks to jernejstrasner for shared HM

Jan Cássio 37 Jul 27, 2022
CryptoSwift is a growing collection of standard and secure cryptographic algorithms implemented in Swift

CryptoSwift Crypto related functions and helpers for Swift implemented in Swift. (#PureSwift) Note: The main branch follows the latest currently relea

Marcin Krzyzanowski 9.4k Jan 9, 2023
Simple and secure hashing in Swift with the SipHash algorithm

SipHash ⚠️ WARNING This package has been obsoleted by the Hasher type and the Hashable.hash(into:) requirement introduced in Swift 4.2. Using this pac

null 262 Dec 19, 2022
A framework for the JOSE standards JWS, JWE, and JWK written in Swift.

JOSESwift is a modular and extensible framework for the JOSE standards JWS, JWE, and JWK written in Swift. ?? Please note that this implementation of

Airside Mobile, Inc. 162 Dec 15, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Dec 30, 2022
BitWiser - A simple library to help you in dealing with bytes, bits and nibbles

BitWiser Bitwiser is a collection of methods and properties that makes you work

Andrea Finollo 19 Dec 27, 2022
Demonstration library for using the Secure Enclave on iOS

SecureEnclaveCrypto This project shows you how to create a keypair where as the private key is stored in the secure enclave sign a string / some data

Trail of Bits 272 Jan 7, 2023
A wrapper for Apple's Common Crypto library written in Swift.

IDZSwiftCommonCrypto A Swift wrapper for Apple's CommonCrypto library. IDZSwiftCommonCrypto works with both CocoaPods and Cathage. For more details on

idz 472 Dec 12, 2022
A pure Swift implementation of MD5

SwiftMD5 SwiftMD5 is a pure Swift implementation for the MD5 algorithm. Usage import SwiftMD5 "The quick brown fox jumps over the lazy dog".md5 // "9

Matthew Purland 11 Sep 25, 2021
🍕 MD5 in pure Swift

SwiftHash ❤️ Support my app ❤️ Push Hero - pure Swift native macOS application to test push notifications Quick Access - Organise files in the Mac men

Khoa 207 Dec 24, 2022