A small collection of cryptographic functions based on the JavaScript WebCrypto API.
A small collection of cryptographic functions based on the JavaScript WebCrypto API. Allows you to share the same crypto between a native iOS/OSX application and a web application.
The original CryptoJS.swift library was developed in 2015 as I needed a way to share the same cryptography between a Swift application and a web app. My goal was achieved by using the same JavaScript CryptoJS library in both environments. CryptoJS is no longer maintained and suffers severe performance limitations over the new WebCrypto API.
This project leverages the power of the WebCrypto API while keeping backwards compatibility with CryptoJS.swift. All methods are asynchronous and run on a separate thread.
In comparison with other available solutions, here are the results obtained when encrypting a 10MB file with AES-256 on a 2.6 GHz Intel Core i7.
RNCryptor 92ms
openSSL: 139ms
WebCrypto.swift: 1545ms
CryptoSwift: 5255ms
let crypto = WebCrypto()
WebCrypto.swift works with Swift’s Data
object. If you need to pass a string to a method, you first need to convert it to Data
before passing it as an input.
Convert String
to Data
:
let data = Data("This is a string".utf8)
Convert Data
to String
:
let string = String(data: data, encoding: .utf8)
Convert Data
to hex encoded string:
let hex = crypto.hexEncodedStringFromData(data)
Convert hex encoded string to Data
:
let data = crypto.dataFromHexEncodedString(hex)
Convert Data
to base64 string:
let base64 = data.base64EncodedString(options: [])
Convert base64 string to Data
:
let data = Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
The algorithm used by WebCrypto.swift is the cipher-block chaining (CBC) mode. For key generation, it uses PKCS7 as the padding method.
WebCrypto.swift supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a password, AES-256 will be used.
WebCrypto.swift uses a salted key derivation algorithm. The salt is a piece of random bytes which are generated when encrypting, and stored in the file header; upon decryption, the salt is retrieved from the header, and the key and IV are recomputed from the provided password and the salt value.
The key derivation algorithm is the same as the one used by openSSL, making it compatible with openSSL and other libraries like CryptoJS.
let input = Data("This is a string".utf8)
let password = "password123"
crypto.encrypt(data: input, password: password, callback: {(encrypted: Data?, error: Error?) in
print(encrypted!)
})
crypto.decrypt(data: encrypted, password: password, callback: {(decrypted: Data?, error: Error?) in
print(String(data: decrypted!, encoding: .utf8)!)
})
This method requires a key and an IV in hexadecimal format. Use the generateKey and generateIv methods if you need to generate a new key and IV. Remember to never re-use an initialization vector. Always generate a new IV every time you encrypt.
let input = Data("This is a string".utf8)
let key = "6f0f1c6f0e56afd327ff07b7b63a2d8ae91ab0a2f0c8cd6889c0fc1d624ac1b8"
let iv = "92c9d2c07a9f2e0a0d20710270047ea2"
crypto.encrypt(data: input, key: key, iv: iv, callback: {(encrypted: Data?, error: Error?) in
print(encrypted!)
})
crypto.decrypt(data: encrypted, key: key, iv: iv, callback: {(encrypted: Data?, error: Error?) in
print(String(data: decrypted!, encoding: .utf8)!)
})
This method generates 128, 192, or 256-bit hex-encoded keys. If the length parameter is omitted, the output is a 256-bit key by default.
crypto.generateKey(callback: {(key: String?, error: Error?) in
print(key!) // aacdc64d6a3f88617af1ce43666970f0e915372cadda8ecb992d215b282a8c17
})
crypto.generateKey(length: 192, callback: {(key: String?, error: Error?) in
print(key!) // 8c675b785838af61c4803c84fe3ba858a4556bdfcafc6c33
})
crypto.generateKey(length: 128, callback: {(key: String?, error: Error?) in
print(key!) // dc1afda2e1bc5f9bd513a658b853cdec
})
This method generates a 16-bit hex-encoded IV. Remember to never re-use an initialization vector. Always generate a new IV every time you encrypt.
crypto.generateIv(callback: {(iv: String?, error: Error?) in
print(iv!) // a408350a6ef6ceb8883173778d700b0a
})
This method lets you get cryptographically strong random values. The output is a hex-encoded string. Do not generate keys using this method. Use the generateKey method instead.
crypto.generateRandomNumber(length: 16, callback: {(number: String?, error: Error?) in
print(number!) // aca73dd1c406bf498f1c07a3d607da9f
})
These methods compute the hash of a data object and output its hexadecimal digest.
let input = Data("This is a string".utf8)
crypto.sha1(data: input, callback: {(hash: String?, error: Error?) in
print(hash!) // 8332d2a25bf1a039d8d296a7b7513960b191d95a
})
crypto.sha256(data: input, callback: {(hash: String?, error: Error?) in
print(hash!) // a2a0d2d2f3046785436e99dcdc0a2a31b41555eed11750e0067b177b99b6c435
})
crypto.sha384(data: input, callback: {(hash: String?, error: Error?) in
print(hash!) // e17d41b167194e4836c63bf3cdcf15b2478cb6fda5887485d5f568c98ed45e3a9bab16e7fe68aa8fe14f683f1144fb3a
})
crypto.sha512(data: input, callback: {(hash: String?, error: Error?) in
print(hash!) // bc5d1ce2a9287ab94f1ed7eff379fbdab5e10d79f8f9dc4f921a2511f418e84561c8d6f63120cd960ea1f48afe09b3bffe2232bb920cc78a2bc873e05e76b30c
})
Check whether the error
value is non-nil to know if an error has occurred.
let input = Data("This is a string".utf8)
let password = "password123"
crypto.encrypt(data: input, password: password, callback: {(encrypted: Data?, error: Error?) in
if let errorMessage = error {
// Something went wrong
print(errorMessage)
}else{
// Success
print(encrypted!)
}
})
When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.
Update the README.md with details of changes to the library.
Update the examples by demonstrating the changes to the library.
Build the project and test all the features before submitting your pull request.
This project is licensed under the MIT License - see the LICENSE file for details.