{"id":119,"date":"2020-03-07T23:43:24","date_gmt":"2020-03-07T23:43:24","guid":{"rendered":"https:\/\/fred.appelman.net\/?p=119"},"modified":"2020-03-08T09:35:11","modified_gmt":"2020-03-08T09:35:11","slug":"encrypting-and-decrypting-using-apple-cryptokit-with-user-specified-password","status":"publish","type":"post","link":"https:\/\/fred.appelman.net\/?p=119","title":{"rendered":"Encrypting and Decrypting using Apple CryptoKit with user specified password"},"content":{"rendered":"<div class=\"entry\">\n\n\n<h2 class=\"wp-block-heading\"><\/h2>\n\n\n\n<p>The examples provided in the documentation from Apple <code>CryptoKit<\/code> show examples where you use the same <code>key<\/code> bot for encryption and decryption. <\/p>\n\n\n\n<p>What it doesn&#8217;t specify how this practically works. How do you make the key and how do you make such thing work in practice.<\/p>\n\n\n\n<p>This article given an example how this can be done. It assumes that the CrytoKit library<br>\nis already installed. See <a href=\"https:\/\/github.com\/apple\/swift-crypto\">https:\/\/github.com\/apple\/swift-crypto<\/a> for instructions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1 &#8211; create the key<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ Create an ecnryption key from a given password\n\/\/\/ - Parameter password: The password that is used to generate the key\nfunc keyFromPassword(_ password: String) -> SymmetricKey {\n  \/\/ Create a SHA256 hash from the provided password\n  let hash = SHA256.hash(data: password.data(using: .utf8)!)\n  \/\/ Convert the SHA256 to a string. This will be a 64 byte string\n  let hashString = hash.map { String(format: \"%02hhx\", $0) }.joined()\n  \/\/ Convert to 32 bytes\n  let subString = String(hashString.prefix(32))\n  \/\/ Convert the substring to data\n  let keyData = subString.data(using: .utf8)!\n\n  \/\/ Create the key use keyData as the seed\n  return SymmetricKey(data: keyData)\n}<\/code><\/pre>\n\n\n\n<p>The above method will create an encryption\/decryption key where the password is used as the seed. The key <strong>must<\/strong> have a length of 256 bits, i.e. 32 bytes.<\/p>\n\n\n\n<p>This will then result in this initial code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import Foundation\nimport Crypto\n\nlet myPassword = \"my secret\"\nlet key = keyFromPassword(myPassword)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2 &#8211; Encrypt the data<\/h3>\n\n\n\n<p>For the encryption we create a method that can encrypt <code>Codable<\/code> objects:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ Encrypt the given object that must be Codable and \n\/\/\/ return the encrypted object as a base64 string\n\/\/\/ - Parameters:\n\/\/\/   - object: The object to encrypt\n\/\/\/   - key: The key to use for the encryption\nfunc encryptCodableObject&lt;T: Codable>(_ object: T, usingKey key: SymmetricKey) throws -> String {\n  \/\/ Convert to JSON in a Data record\n  let encoder = JSONEncoder()\n  let userData = try encoder.encode(object)\n\n  \/\/ Encrypt the userData\n  let encryptedData = try ChaChaPoly.seal(userData, using: key)\n\n  \/\/ Convert the encryptedData to a base64 string which is the\n  \/\/ format that it can be transported in\n  return encryptedData.combined.base64EncodedString()\n}<\/code><\/pre>\n\n\n\n<p>This will then lead to the following incremental code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import Foundation\nimport Crypto\n\nlet myPassword = \"my secret\"\nlet key = keyFromPassword(myPassword)\n\n\/\/ A sample structure to encode\nstruct User: Codable {\n  let name: String\n  let password: String\n}\n\n\/\/ Create a user that will be encrypted\nlet user = User(name: \"J.Doe\", password: \"Another Secret\")\nlet base64EncodedString = try encryptCodableObject(user, usingKey: key)\n\/\/ base64EncodedString will have value:\n\/\/ fkcOR\/H0nRWHemOPf3eUUxQGO2NR2nSC4vz0no1N5Dnd5Ia\\\n\/\/ qXiqtxeZeJb8hY0k+M8YhE+5uzZL85o7WUjJWq\/8A0IDO+kNt<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3 &#8211; Decrypt the data<\/h3>\n\n\n\n<p>For the decryption we create a method that can decrypt the base64 string into <br> the target <code>Codable<\/code>` object using the decryption key.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ Decrypt a given string into a Codable object\n\/\/\/ - Parameters:\n\/\/\/   - type: The type of the resulting object\n\/\/\/   - string: The string to decrypt\n\/\/\/   - key: The key to use for the decryption\nfunc decryptStringToCodableOject&lt;T: Codable>(_ type: T.Type, from string: String, \n                                             usingKey key: SymmetricKey) throws -> T {\n  \/\/ Convert the base64 string into a Data object\n  let data = Data(base64Encoded: string)!\n  \/\/ Put the data in a sealed box\n  let box = try ChaChaPoly.SealedBox(combined: data)\n  \/\/ Extract the data from the sealedbox using the decryption key\n  let decryptedData = try ChaChaPoly.open(box, using: key)\n  \/\/ The decrypted block needed to be json decoded\n  let decoder = JSONDecoder()\n  let object = try decoder.decode(type, from: decryptedData)\n  \/\/ Return the new object\n  return object\n}<\/code><\/pre>\n\n\n\n<p>which then leads to the final code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import Foundation\nimport Crypto\n\nlet myPassword = \"my secret\"\nlet key = keyFromPassword(myPassword)\n\n\/\/ A sample structure to encode\nstruct User: Codable {\n  let name: String\n  let password: String\n}\n\n\/\/ Create a user that will be encrypted\nlet user = User(name: \"J.Doe\", password: \"Another Secret\")\nlet base64EncodedString = try encryptCodableObject(user, usingKey: key)\n\/\/ base64EncodedString will have value:\n\/\/ fkcOR\/H0nRWHemOPf3eUUxQGO2NR2nSC4vz0no1N5Dnd5Ia\\\n\/\/ qXiqtxeZeJb8hY0k+M8YhE+5uzZL85o7WUjJWq\/8A0IDO+kNt\n\nlet newObject = try decryptStringToCodableOject(User.self, from: base64EncodedString, usingKey: key)\nprint(newObject.name)      \/\/ J.Doe\nprint(newObject.password)  \/\/ Another Secret<\/code><\/pre>\n\n\n\n<p>The intermediate base64 string can be stored in for example the keychain or send through a socket or email.  When the receiving side knows the password they can construct the decryption key and decrypt the message.<\/p>\n\n\n\n<p><\/p>\n\n\n<\/div>","protected":false},"excerpt":{"rendered":"<p>The examples provided in the documentation from Apple CryptoKit show examples where you use the same key bot for encryption and decryption. What it doesn&#8217;t specify how this practically works. How do you make the key and how do you make such thing work in practice. This article given an example how this can be &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,25,24,10],"tags":[22,21,20,23,16,19],"class_list":{"0":"post-119","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-cryptokit","7":"category-decryption","8":"category-encryption","9":"category-swift","10":"tag-cryptokit","11":"tag-decryption","12":"tag-encryption","13":"tag-seed","14":"tag-swift","15":"tag-swift-5","16":"anons"},"_links":{"self":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=119"}],"version-history":[{"count":5,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":138,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/119\/revisions\/138"}],"wp:attachment":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}