{"id":2024,"url":"https://github.com/henrinormak/Heimdall","last_synced_at":"2025-08-02T05:33:32.025Z","repository":{"id":30900611,"uuid":"34458389","full_name":"henrinormak/Heimdall","owner":"henrinormak","description":"Heimdall is a wrapper around the Security framework for simple encryption/decryption operations.","archived":false,"fork":false,"pushed_at":"2020-09-25T07:38:58.000Z","size":470,"stargazers_count":401,"open_issues_count":13,"forks_count":68,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-04-23T19:19:52.974Z","etag":null,"topics":["aes","encrypted-messages","ios","rsa","security","swift"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/henrinormak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-23T13:38:18.000Z","updated_at":"2024-04-17T06:41:16.000Z","dependencies_parsed_at":"2022-08-21T02:50:38.768Z","dependency_job_id":null,"html_url":"https://github.com/henrinormak/Heimdall","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrinormak%2FHeimdall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrinormak%2FHeimdall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrinormak%2FHeimdall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrinormak%2FHeimdall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/henrinormak","download_url":"https://codeload.github.com/henrinormak/Heimdall/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228443869,"owners_count":17920804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes","encrypted-messages","ios","rsa","security","swift"],"created_at":"2024-01-05T20:16:01.515Z","updated_at":"2024-12-06T09:30:50.822Z","avatar_url":"https://github.com/henrinormak.png","language":"Swift","funding_links":[],"categories":["UI","Text","Swift"],"sub_categories":["Layout","Other free courses","Other Testing","Keychain"],"readme":"![Heimdall Helmet](/Images/heimdall_icon.png \"Heimdall Helmet\")\n\n![Build Status](https://api.travis-ci.org/henrinormak/Heimdall.svg)\n![CocoaPods compatible](https://img.shields.io/cocoapods/v/Heimdall.svg)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n\n# Heimdall\n\nIn Norse mythology, Heimdall is the gatekeeper of Bifröst, the rainbow road connecting Midgard, realm of the humans, to Asgard, the realm of gods.\n\nIn iOS, Heimdall serves as a gatekeeper between Security framework and the UI, offering a nice wrapper around the C APIs for encrypting, decrypting, signing and verifying messages.\n\nFurthermore, Heimdall also helps maintain the public-private RSA key-pair in Keychain, allowing both creating as well as deleting the key pairs.\n\n## Requirements\n\nHeimdall requires Swift 3 and works with only Xcode 8 and above\n\n## Installation\n\n### CocoaPods\n\nHeimdall is available as a CocoaPod, simply add the following line to your Podfile\n\n```ruby\npod 'Heimdall', '~\u003e 1.1.0'\n```\n\nAlso, make sure your podfile includes the following line, which is necessary to support Swift frameworks\n\n```ruby\nuse_frameworks!\n```\n\n### Carthage\n\nSimply include the following line in your Cartfile\n\n```\ngithub \"henrinormak/Heimdall\"\n```\n\nNote that Heimdall produces two frameworks in the Carthage build directory - `Heimdall.framework` and `CommonCrypto.framework`, you only need to include/embed `Heimdall.framework` into your project.\n\n### Subproject\n\nAs Heimdall makes use of `CommonCrypto` and has it wrapped in a pseudo-module, the easiest way to use Heimdall is to include the entire project as a subproject in your workspace.\n\nTo do this, include `Heimdall.xcodeproj` (found in Heimdall folder) into your Xcode workspace. Then specify the `Heimdall` target as a **Target Dependency** for your main application target.\n\n![Target Dependency selection in Xcode](/Images/target_dependency.png?raw=true \"Target Dependency\")\n\nFinally, make sure Heimdall is listed under the **Embedded Binaries** section in Xcode\n\n![Embedded Binaries under application target settings](/Images/embedded_binary.png?raw=true \"Embedded Binary\")\n\n### Directly\n\nAlthough not recommended, you can also add Heimdall directly, by including `Heimdall.swift` in your project.\n\n## Usage\n\nUsing Heimdall is simple, for public-private key-pair, you just have to create an instance, which can be used for encryption/decryption, signing/verifying.\n\nWith this method you can locally encrypt data to be stored on disk or in a database, without putting everything in the Keychain.\n\n```swift\nif let heimdall = Heimdall(tagPrefix: \"com.example\") {\n    let testString = \"This is a test string\"\n\n    // Encryption/Decryption\n    if let encryptedString = heimdall.encrypt(testString) {\n        println(encryptedString) // \"cQzaQCQLhAWqkDyPoHnPrpsVh...\"\n\n        if let decryptedString = heimdall.decrypt(encryptedString) {\n            println(decryptedString) // \"This is a test string\"\n        }\n    }\n\n    // Signatures/Verification\n    if let signature = heimdall.sign(testString) {\n        println(signature) // \"fMVOFj6SQ7h+cZTEXZxkpgaDsMrki...\"\n        var verified = heimdall.verify(testString, signatureBase64: signature)\n        println(verified) // True\n\n        // If someone meddles with the message and the signature becomes invalid\n        verified = heimdall.verify(testString + \"injected false message\",\n                                    signatureBase64: signature)\n        println(verified) // False\n    }\n}\n```\n\n### Note on encryption/decryption\n\nAs RSA imposes a limit on the length of message that can be enrcypted, Heimdall uses a mix of AES and RSA to encrypt messages of arbitrary length. This is done in the following manner:\n\n1. A random AES key of suitable length is generated, the length is based on the size of the RSA key pair (either 128, 192 or 256 bits) [*](https://github.com/henrinormak/Heimdall/blob/master/Heimdall/Heimdall.swift#L194-L202)\n2. The message is encrypted with this AES key\n3. The key is encrypted with the public part of the RSA key pair (and padded to the correct block size) [*](https://github.com/henrinormak/Heimdall/blob/master/Heimdall/Heimdall.swift#L213-L218)\n4. The payload is built, containing the encrypted key, followed by the encrypted message. During decryption, the first block is always assumed to be the RSA encrypted AES key, this is why Heimdall can only decrypt messages encrypted by other Heimdall instances (or code that is compatible with Heimdall's logic) [*](https://github.com/henrinormak/Heimdall/blob/master/Heimdall/Heimdall.swift#L259-L262)\n\n### Complex use case\n\nA more complex use case involves exchanging encrypted messages between multiple Heimdall instances, which can be situated on multiple different hosts.\n\nFirst step is to share your public key with another party:\n\n```swift\nlet localHeimdall = Heimdall(tagPrefix: \"com.example\")\nif let heimdall = localHeimdall, publicKeyData = heimdall.publicKeyDataX509() {\n\n    var publicKeyString = publicKeyData.base64EncodedString()\n\n    // If you want to make this string URL safe,\n    // you have to remember to do the reverse on the other side later\n    publicKeyString = publicKeyString.replacingOccurrences(of: \"/\", with: \"_\")\n    publicKeyString = publicKeyString.replacingOccurrences(of: \"+\", with: \"-\")\n\n    println(publicKeyString) // Something along the lines of \"MIGfMA0GCSqGSIb3DQEBAQUAA...\"\n\n    // Data transmission of public key to the other party\n}\n```\n\nSecond step, acting as the recipient (the one that wants to send the encrypted message), you receive the public key extracted and create a matching Heimdall instance:\n\n```swift\n// On other party, assuming keyData contains the received public key data\nif let partnerHeimdall = Heimdall(publicTag: \"com.example.partner\", publicKeyData: keyData) {\n    // Transmit some message to the partner\n    let message = \"This is a secret message to my partner\"\n    let encryptedMessage = partnerHeimdall.encrypt(message)\n\n    // Transmit the encryptedMessage back to the origin of the public key\n}\n```\n\nFinally, having received the encrypted message, the party that sent out the public key can decrypt it using the original Heimdall instance they had:\n\n```swift\n// Initial host receives encryptedMessage\nif let heimdall = localHeimdall {\n    if let decryptedMessage = heimdall.decrypt(encryptedMessage) {\n        println(decryptedMessage) // \"This is a secret message to my partner\"\n    }\n}\n```\n\nThe workflow should be mirrored on all hosts, extracting their public keys and sharing those to all other parties. The public keys can be used to construct special Heimdall instances that are only able to encrypt messages and verify signatures.\n\n## Contributing and Current Work\n\nContributions to the codebase are very welcome, for ideas on what is needed, have a look through the open issues. In addition, any suggestions regarding the following topics are welcome:\n\n* Security, interacting with the Keychain, making sure the results are kept securely etc.\n* Tests, adding tests would also likely increase security\n* Additional configurability, perhaps allowing non-permanent keys\n* Error handling, currently most of the API simply returns `nil`s whenever an error occurs, this should be changed and proper error reporting should be implemented\n* Reducing the number of optionals in the public API of the Heimdall instances.\n\n## Contact\n\nIf you have any questions, don't hesitate to contact me.\nIn case of bugs, create an issue here on GitHub\n\nHenri Normak\n\n- http://github.com/henrinormak\n- http://twitter.com/henrinormak\n\n## License\n\n```\nThe MIT License (MIT)\n\nCopyright (c) 2015 Henri Normak\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrinormak%2FHeimdall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenrinormak%2FHeimdall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrinormak%2FHeimdall/lists"}