├── .editorconfig ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── android.yml │ ├── linux.yml │ └── macos.yml ├── .gitignore ├── .mailmap ├── .spi.yml ├── .swiftformat ├── CHANGELOG ├── CNAME ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.txt ├── CryptoSwift-TestHostApp ├── AppDelegate.swift ├── Default-568h@2x.png └── Info.plist ├── CryptoSwift.podspec ├── CryptoSwift.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── CryptoSwift.xccheckout │ │ ├── CryptoSwift.xcscmblueprint │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ ├── IDETemplateMacros.plist │ └── xcschemes │ ├── CryptoSwift-TestHostApp.xcscheme │ ├── CryptoSwift.xcscheme │ ├── Tests.xcscheme │ ├── TestsPerformance-Mac.xcscheme │ └── TestsPerformance-iOS.xcscheme ├── Info.plist ├── LICENSE ├── Makefile ├── Package.swift ├── README.md ├── Sources ├── CryptoSwift.h └── CryptoSwift │ ├── AEAD │ ├── AEAD.swift │ ├── AEADChaCha20Poly1305.swift │ └── AEADXChaCha20Poly1305.swift │ ├── AES.Cryptors.swift │ ├── AES.swift │ ├── ASN1 │ ├── ASN1.swift │ ├── ASN1Decoder.swift │ ├── ASN1Encoder.swift │ └── ASN1Scanner.swift │ ├── Array+Extension.swift │ ├── Authenticator.swift │ ├── BatchedCollection.swift │ ├── Bit.swift │ ├── BlockCipher.swift │ ├── BlockDecryptor.swift │ ├── BlockEncryptor.swift │ ├── BlockMode │ ├── BlockMode.swift │ ├── BlockModeOptions.swift │ ├── CBC.swift │ ├── CCM.swift │ ├── CFB.swift │ ├── CTR.swift │ ├── CipherModeWorker.swift │ ├── ECB.swift │ ├── GCM.swift │ ├── OCB.swift │ ├── OFB.swift │ └── PCBC.swift │ ├── Blowfish.swift │ ├── CBCMAC.swift │ ├── CMAC.swift │ ├── CS_BigInt │ ├── Addition.swift │ ├── BigInt.swift │ ├── BigUInt.swift │ ├── BitwiseOps.swift │ ├── CS.swift │ ├── Codable.swift │ ├── Comparable.swift │ ├── DataConversion.swift │ ├── Division.swift │ ├── Exponentiation.swift │ ├── FloatingPointConversion.swift │ ├── GCD.swift │ ├── Hashable.swift │ ├── IntegerConversion.swift │ ├── Multiplication.swift │ ├── PrimeTest.swift │ ├── Random.swift │ ├── Shifts.swift │ ├── SquareRoot.swift │ ├── Strideable.swift │ ├── StringConversion.swift │ ├── Subtraction.swift │ └── WordsAndBits.swift │ ├── ChaCha20.swift │ ├── Checksum.swift │ ├── Cipher.swift │ ├── Collection+Extension.swift │ ├── CompactMap.swift │ ├── Cryptor.swift │ ├── Cryptors.swift │ ├── Digest.swift │ ├── DigestType.swift │ ├── Foundation │ ├── AES+Foundation.swift │ ├── Array+Foundation.swift │ ├── Blowfish+Foundation.swift │ ├── ChaCha20+Foundation.swift │ ├── Data+Extension.swift │ ├── HMAC+Foundation.swift │ ├── Rabbit+Foundation.swift │ ├── String+FoundationExtension.swift │ ├── Utils+Foundation.swift │ └── XChaCha20+Foundation.swift │ ├── Generics.swift │ ├── HKDF.swift │ ├── HMAC.swift │ ├── ISO10126Padding.swift │ ├── ISO78164Padding.swift │ ├── Int+Extension.swift │ ├── MD5.swift │ ├── NoPadding.swift │ ├── Operators.swift │ ├── PEM │ └── DER.swift │ ├── PKCS │ ├── PBKDF1.swift │ ├── PBKDF2.swift │ ├── PKCS1v15.swift │ ├── PKCS5.swift │ ├── PKCS7.swift │ └── PKCS7Padding.swift │ ├── Padding.swift │ ├── Poly1305.swift │ ├── PrivacyInfo.xcprivacy │ ├── RSA │ ├── RSA+Cipher.swift │ ├── RSA+Signature.swift │ └── RSA.swift │ ├── Rabbit.swift │ ├── SHA1.swift │ ├── SHA2.swift │ ├── SHA3.swift │ ├── Scrypt.swift │ ├── SecureBytes.swift │ ├── Signature.swift │ ├── StreamDecryptor.swift │ ├── StreamEncryptor.swift │ ├── String+Extension.swift │ ├── UInt128.swift │ ├── UInt16+Extension.swift │ ├── UInt32+Extension.swift │ ├── UInt64+Extension.swift │ ├── UInt8+Extension.swift │ ├── Updatable.swift │ ├── Utils.swift │ ├── XChaCha20.swift │ └── ZeroPadding.swift ├── Tests ├── CryptoSwiftTests │ ├── AESCCMTests.swift │ ├── AESOCBTests.swift │ ├── AESTests.swift │ ├── AESTestsPerf.swift │ ├── ASN1Tests.swift │ ├── Access.swift │ ├── BlowfishTests.swift │ ├── Bridging.h │ ├── CBCMacTests.swift │ ├── CMACTests.swift │ ├── ChaCha20Poly1305Tests.swift │ ├── ChaCha20Tests.swift │ ├── ChaCha20TestsPerf.swift │ ├── DigestTests.swift │ ├── DigestTestsPerf.swift │ ├── Error+Extension.swift │ ├── ExtensionsTest.swift │ ├── ExtensionsTestPerf.swift │ ├── HKDFTests.swift │ ├── HMACTests.swift │ ├── PBKDF.swift │ ├── PBKDFPerf.swift │ ├── PaddingTests.swift │ ├── Poly1305Tests.swift │ ├── RSASecKeyTests.swift │ ├── RSATests.swift │ ├── RabbitTests.swift │ ├── RabbitTestsPerf.swift │ ├── SHATestsPerf.swift │ ├── ScryptTests.swift │ ├── ScryptTestsPerf.swift │ ├── SignatureVerificationTests.swift │ ├── XCTestManifests.swift │ ├── XChaCha20Poly1305Tests.swift │ └── XChaCha20Tests.swift ├── LinuxMain.swift └── TestsPerformance │ └── XCTestManifests.swift ├── _config.yml ├── config ├── CryptoSwift-Debug.xcconfig ├── CryptoSwift-Release.xcconfig ├── CryptoSwift-Shared.xcconfig ├── CryptoSwift-Test.xcconfig ├── CryptoSwift-TestHostApp-Shared.xcconfig ├── CryptoSwift-TestHostApp-Test.xcconfig ├── Project-Debug.xcconfig ├── Project-Release.xcconfig ├── Project-Shared.xcconfig ├── Tests-Shared.xcconfig └── Tests-Test.xcconfig └── scripts ├── build-framework.sh ├── generate-contributors-list.sh └── swiftformat.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | 5 | [*.swift] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [Makefile] 11 | indent_style = tab 12 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @krzyzanowskim 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [krzyzanowskim, NathanFallet] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | 9 | 10 | **Reproduce** 11 | Steps to reproduce: 12 | 1. 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # 2 | 3 | Checklist: 4 | - [ ] Correct file headers (see CONTRIBUTING.md). 5 | - [ ] Formatted with [SwiftFormat](https://github.com/nicklockwood/SwiftFormat). 6 | - [ ] Tests added. 7 | 8 | Changes proposed in this pull request: 9 | - 10 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Run tests 21 | uses: skiptools/swift-android-action@v2 22 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-20.04 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Swift Package Build 21 | run: swift build -v 22 | 23 | - name: Run tests 24 | run: swift test -c release -Xswiftc -enable-testing -Xswiftc -DCI -Xswiftc -Xfrontend -Xswiftc -solver-memory-threshold -Xswiftc -Xfrontend -Xswiftc 999999999 25 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Select Xcode Version 21 | uses: maxim-lobanov/setup-xcode@v1 22 | with: 23 | xcode-version: latest-stable 24 | 25 | - name: Swift Package Build 26 | run: swift build -v 27 | 28 | - name: Run tests 29 | run: swift test -c release -Xswiftc -enable-testing -Xswiftc -DCI -Xswiftc -Xfrontend -Xswiftc -solver-memory-threshold -Xswiftc -Xfrontend -Xswiftc 999999999 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Xcode ### 2 | .build/ 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.xcuserstate 17 | timeline.xctimeline 18 | .swiftpm/xcode 19 | Package.resolved 20 | CryptoSwift.xcframework 21 | 22 | /Framework 23 | .DS_Store 24 | Carthage/Build 25 | 26 | .idea 27 | .vscode 28 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Marcin Krzyzanowski <758033+krzyzanowskim@users.noreply.github.com> 2 | Marcin Krzyzanowski 3 | Marcin Krzyzanowski 4 | Marcin Krzyzanowski 5 | Luis Reisewitz 6 | Nathan Fallet -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [CryptoSwift] -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | 2 | --exclude .build, Carthage, DerivedData, .git, Tests/LinuxMain.swift, Tests/CryptoSwiftTests/XCTestManifests.swift, Tests/TestsPerformance/XCTestManifests.swift 3 | 4 | --swiftversion 5.0 5 | --allman false 6 | --commas always 7 | --comments indent 8 | --elseposition same-line 9 | --empty void 10 | --exponentcase lowercase 11 | --exponentgrouping disabled 12 | --fractiongrouping disabled 13 | --header ignore 14 | --octalgrouping 4,8 15 | --decimalgrouping 3,6 16 | --binarygrouping 4,8 17 | --hexgrouping ignore 18 | --hexliteralcase lowercase 19 | --ifdef indent 20 | --indent 2 21 | --indentcase true 22 | --importgrouping testable-bottom 23 | --linebreaks lf 24 | --operatorfunc spaced 25 | --patternlet inline 26 | --ranges no-space 27 | --self insert 28 | --semicolons inline 29 | --stripunusedargs closure-only 30 | --trimwhitespace always 31 | --wraparguments preserve 32 | --wrapcollections before-first 33 | 34 | # rules 35 | 36 | --rules indent, braces, isEmpty, redundantBreak, blankLinesAroundMark, blankLinesAtEndOfScope, blankLinesBetweenScopes, consecutiveBlankLines, consecutiveSpaces, duplicateImports, elseOnSameLine, leadingDelimiters, redundantBreak, redundantExtensionACL, redundantFileprivate, redundantGet, redundantInit, redundantLet, redundantNilInit, redundantObjc, redundantParens, redundantPattern, redundantRawValues, redundantReturn, redundantSelf, redundantVoidReturnType, semicolons, sortedImports, spaceAroundBraces, spaceAroundBrackets, spaceAroundComments, spaceAroundGenerics, spaceAroundOperators, spaceAroundParens, spaceInsideBraces, spaceInsideBrackets, specifiers, strongOutlets, strongifiedSelf, todos, void, wrapArguments, yodaConditions, trailingSpace -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | cryptoswift.io 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at marcin@krzyzanowskim.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | By submitting a pull request, you represent that you have the right to license 2 | your contribution to Marcin Krzyżanowski and the community, and agree by submitting the patch that your contributions are licensed under the CryptoSwift project license. 3 | 4 | --- 5 | 6 | Before submitting the pull request, please make sure you have tested your changes. 7 | 8 | --- 9 | 10 | For new files, please use the correct file header: 11 | 12 | ``` 13 | // 14 | // CryptoSwift 15 | // 16 | // Copyright (C) Marcin Krzyżanowski 17 | // This software is provided 'as-is', without any express or implied warranty. 18 | // 19 | // In no event will the authors be held liable for any damages arising from the use of this software. 20 | // 21 | // Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 22 | // 23 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 24 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 25 | // - This notice may not be removed or altered from any source or binary distribution. 26 | // 27 | ``` 28 | -------------------------------------------------------------------------------- /CryptoSwift-TestHostApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import UIKit 17 | 18 | @UIApplicationMain 19 | class AppDelegate: UIResponder, UIApplicationDelegate { 20 | 21 | var window: UIWindow? 22 | 23 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 24 | // Override point for customization after application launch. 25 | true 26 | } 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CryptoSwift-TestHostApp/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzyzanowskim/CryptoSwift/f03fd66a07e5a79f0f06317a043b69764198803f/CryptoSwift-TestHostApp/Default-568h@2x.png -------------------------------------------------------------------------------- /CryptoSwift-TestHostApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIRequiredDeviceCapabilities 24 | 25 | armv7 26 | 27 | UIRequiresFullScreen 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /CryptoSwift.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "CryptoSwift" 3 | s.version = "1.8.4" 4 | s.source = { :git => "https://github.com/krzyzanowskim/CryptoSwift.git", :tag => "#{s.version}" } 5 | s.summary = "Cryptography in Swift. SHA, MD5, CRC, PBKDF, Poly1305, HMAC, CMAC, HDKF, Scrypt, ChaCha20, Rabbit, Blowfish, AES, RSA." 6 | s.description = "Cryptography functions and helpers for Swift implemented in Swift. SHA-1, SHA-2, SHA-3, MD5, PBKDF1, PBKDF2, Scrypt, CRC, Poly1305, HMAC, ChaCha20, Rabbit, Blowfish, AES, RSA" 7 | s.homepage = "https://github.com/krzyzanowskim/CryptoSwift" 8 | s.license = {:type => "Attribution", :file => "LICENSE"} 9 | s.authors = {'Marcin Krzyżanowski' => 'marcin@krzyzanowskim.com'} 10 | s.social_media_url = "https://x.com/krzyzanowskim" 11 | s.cocoapods_version = '>= 1.10.0' 12 | s.swift_version = "5.6" 13 | s.ios.deployment_target = "11.0" 14 | s.osx.deployment_target = "10.13" 15 | s.watchos.deployment_target = "4.0" 16 | s.tvos.deployment_target = "11.0" 17 | s.source_files = "Sources/CryptoSwift/**/*.swift" 18 | s.requires_arc = true 19 | s.resource_bundles = {'CryptoSwift' => ['Sources/CryptoSwift/PrivacyInfo.xcprivacy']} 20 | end 21 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 7266B6DF-1CD3-4383-821A-42E5BE4580E8 9 | IDESourceControlProjectName 10 | CryptoSwift 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53 14 | github.com:krzyzanowskim/CryptoSwift.git 15 | 16 | IDESourceControlProjectPath 17 | CryptoSwift.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:krzyzanowskim/CryptoSwift.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53 36 | IDESourceControlWCCName 37 | CryptoSwift 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krzyzanowskim/CryptoSwift/f03fd66a07e5a79f0f06317a043b69764198803f/CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/CryptoSwift.xcscmblueprint -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/xcshareddata/IDETemplateMacros.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FILEHEADER 6 | // CryptoSwift 7 | // 8 | // Copyright (C) 2014-__YEAR__ Marcin Krzyżanowski <marcin@krzyzanowskim.com> 9 | // This software is provided 'as-is', without any express or implied warranty. 10 | // 11 | // In no event will the authors be held liable for any damages arising from the use of this software. 12 | // 13 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 14 | // 15 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 16 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 17 | // - This notice may not be removed or altered from any source or binary distribution. 18 | // 19 | 20 | 21 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/xcshareddata/xcschemes/CryptoSwift-TestHostApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/xcshareddata/xcschemes/TestsPerformance-Mac.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /CryptoSwift.xcodeproj/xcshareddata/xcschemes/TestsPerformance-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014-3099 Marcin Krzyżanowski 2 | This software is provided 'as-is', without any express or implied warranty. 3 | 4 | In no event will the authors be held liable for any damages arising from the use of this software. 5 | 6 | Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 7 | 8 | - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 9 | - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 10 | - This notice may not be removed or altered from any source or binary distribution. 11 | - Redistributions of any form whatsoever must retain the following acknowledgment: 'This product includes software developed by the "Marcin Krzyzanowski" (http://krzyzanowskim.com/).' 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: frameworks 2 | 3 | CWD := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))) 4 | 5 | frameworks: 6 | $(CWD)/scripts/build-framework.sh 7 | @echo "Framework built in $(CWD)/CryptoSwift.xcframework" 8 | 9 | all: frameworks 10 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.6 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "CryptoSwift", 7 | platforms: [ 8 | .macOS(.v10_13), .macCatalyst(.v13), .iOS(.v11), .tvOS(.v11), .watchOS(.v4), .custom("visionos", versionString: "1.0") 9 | ], 10 | products: [ 11 | .library( 12 | name: "CryptoSwift", 13 | targets: ["CryptoSwift"] 14 | ) 15 | ], 16 | targets: [ 17 | .target(name: "CryptoSwift", resources: [.copy("PrivacyInfo.xcprivacy")]), 18 | .testTarget(name: "CryptoSwiftTests", dependencies: ["CryptoSwift"]) 19 | ], 20 | swiftLanguageVersions: [.v5] 21 | ) 22 | -------------------------------------------------------------------------------- /Sources/CryptoSwift.h: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift.h 3 | // CryptoSwift 4 | // 5 | // Created by Sam Soffes on 11/29/15. 6 | // Copyright © 2015 Marcin Krzyzanowski. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for CryptoSwift. 12 | FOUNDATION_EXPORT double CryptoSwiftVersionNumber; 13 | 14 | //! Project version string for CryptoSwift. 15 | FOUNDATION_EXPORT const unsigned char CryptoSwiftVersionString[]; 16 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/AEAD/AEAD.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AEAD.swift 3 | // CryptoSwift 4 | // 5 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // 8 | // In no event will the authors be held liable for any damages arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 11 | // 12 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 13 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | // - This notice may not be removed or altered from any source or binary distribution. 15 | // 16 | // 17 | 18 | // https://www.iana.org/assignments/aead-parameters/aead-parameters.xhtml 19 | 20 | /// Authenticated Encryption with Associated Data (AEAD) 21 | public protocol AEAD { 22 | static var kLen: Int { get } // key length 23 | static var ivRange: Range { get } // nonce length 24 | } 25 | 26 | extension AEAD { 27 | static func calculateAuthenticationTag(authenticator: Authenticator, cipherText: Array, authenticationHeader: Array) throws -> Array { 28 | let headerPadding = ((16 - (authenticationHeader.count & 0xf)) & 0xf) 29 | let cipherPadding = ((16 - (cipherText.count & 0xf)) & 0xf) 30 | 31 | var mac = authenticationHeader 32 | mac += Array(repeating: 0, count: headerPadding) 33 | mac += cipherText 34 | mac += Array(repeating: 0, count: cipherPadding) 35 | mac += UInt64(bigEndian: UInt64(authenticationHeader.count)).bytes() 36 | mac += UInt64(bigEndian: UInt64(cipherText.count)).bytes() 37 | 38 | return try authenticator.authenticate(mac) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/AEAD/AEADChaCha20Poly1305.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AEADChaCha20Poly1305.swift 3 | // CryptoSwift 4 | // 5 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // 8 | // In no event will the authors be held liable for any damages arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 11 | // 12 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 13 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | // - This notice may not be removed or altered from any source or binary distribution. 15 | // 16 | // 17 | // https://tools.ietf.org/html/rfc7539#section-2.8.1 18 | 19 | /// AEAD_CHACHA20_POLY1305 20 | public final class AEADChaCha20Poly1305: AEAD { 21 | public static let kLen = 32 // key length 22 | public static var ivRange = Range(12...12) 23 | 24 | /// Authenticated encryption 25 | public static func encrypt(_ plainText: Array, key: Array, iv: Array, authenticationHeader: Array) throws -> (cipherText: Array, authenticationTag: Array) { 26 | let cipher = try ChaCha20(key: key, iv: iv) 27 | return try self.encrypt(cipher: cipher, plainText, key: key, iv: iv, authenticationHeader: authenticationHeader) 28 | } 29 | 30 | public static func encrypt(cipher: Cipher, _ plainText: Array, key: Array, iv: Array, authenticationHeader: Array) throws -> (cipherText: Array, authenticationTag: Array) { 31 | var polykey = Array(repeating: 0, count: kLen) 32 | var toEncrypt = polykey 33 | polykey = try cipher.encrypt(polykey) 34 | toEncrypt += polykey 35 | toEncrypt += plainText 36 | 37 | let fullCipherText = try cipher.encrypt(toEncrypt) 38 | let cipherText = Array(fullCipherText.dropFirst(64)) 39 | 40 | let tag = try calculateAuthenticationTag(authenticator: Poly1305(key: polykey), cipherText: cipherText, authenticationHeader: authenticationHeader) 41 | return (cipherText, tag) 42 | } 43 | 44 | /// Authenticated decryption 45 | public static func decrypt(_ cipherText: Array, key: Array, iv: Array, authenticationHeader: Array, authenticationTag: Array) throws -> (plainText: Array, success: Bool) { 46 | let cipher = try ChaCha20(key: key, iv: iv) 47 | return try self.decrypt(cipher: cipher, cipherText: cipherText, key: key, iv: iv, authenticationHeader: authenticationHeader, authenticationTag: authenticationTag) 48 | } 49 | 50 | static func decrypt(cipher: Cipher, cipherText: Array, key: Array, iv: Array, authenticationHeader: Array, authenticationTag: Array) throws -> (plainText: Array, success: Bool) { 51 | 52 | let polykey = try cipher.encrypt(Array(repeating: 0, count: self.kLen)) 53 | let mac = try calculateAuthenticationTag(authenticator: Poly1305(key: polykey), cipherText: cipherText, authenticationHeader: authenticationHeader) 54 | guard mac == authenticationTag else { 55 | return (cipherText, false) 56 | } 57 | 58 | var toDecrypt = Array(reserveCapacity: cipherText.count + 64) 59 | toDecrypt += polykey 60 | toDecrypt += polykey 61 | toDecrypt += cipherText 62 | let fullPlainText = try cipher.decrypt(toDecrypt) 63 | let plainText = Array(fullPlainText.dropFirst(64)) 64 | return (plainText, true) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/AES.Cryptors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // MARK: Cryptors 17 | 18 | extension AES: Cryptors { 19 | @inlinable 20 | public func makeEncryptor() throws -> Cryptor & Updatable { 21 | let blockSize = blockMode.customBlockSize ?? AES.blockSize 22 | let worker = try blockMode.worker(blockSize: blockSize, cipherOperation: encrypt, encryptionOperation: encrypt) 23 | if worker is StreamModeWorker { 24 | return try StreamEncryptor(blockSize: blockSize, padding: padding, worker) 25 | } 26 | return try BlockEncryptor(blockSize: blockSize, padding: padding, worker) 27 | } 28 | 29 | @inlinable 30 | public func makeDecryptor() throws -> Cryptor & Updatable { 31 | let blockSize = blockMode.customBlockSize ?? AES.blockSize 32 | let cipherOperation: CipherOperationOnBlock = blockMode.options.contains(.useEncryptToDecrypt) == true ? encrypt : decrypt 33 | let worker = try blockMode.worker(blockSize: blockSize, cipherOperation: cipherOperation, encryptionOperation: encrypt) 34 | if worker is StreamModeWorker { 35 | return try StreamDecryptor(blockSize: blockSize, padding: padding, worker) 36 | } 37 | return try BlockDecryptor(blockSize: blockSize, padding: padding, worker) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/ASN1/ASN1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | // ASN1 Code inspired by Asn1Parser.swift from SwiftyRSA 16 | 17 | import Foundation 18 | 19 | /// A Partial ASN.1 (Abstract Syntax Notation 1) Encoder & Decoder Implementation. 20 | /// 21 | /// - Note: This implementation is limited to a few core types and is not an exhaustive / complete ASN1 implementation 22 | /// - Warning: This implementation has been developed for encoding and decoding DER & PEM files specifically. If you're using this Encoder/Decoder on other ASN1 structures, make sure you test the expected behavior appropriately. 23 | enum ASN1 { 24 | internal enum IDENTIFIERS: UInt8, Equatable { 25 | case SEQUENCE = 0x30 26 | case INTERGER = 0x02 27 | case OBJECTID = 0x06 28 | case NULL = 0x05 29 | case BITSTRING = 0x03 30 | case OCTETSTRING = 0x04 31 | 32 | static func == (lhs: UInt8, rhs: IDENTIFIERS) -> Bool { 33 | lhs == rhs.rawValue 34 | } 35 | 36 | var bytes: [UInt8] { 37 | switch self { 38 | case .NULL: 39 | return [self.rawValue, 0x00] 40 | default: 41 | return [self.rawValue] 42 | } 43 | } 44 | } 45 | 46 | /// An ASN1 node 47 | internal enum Node: CustomStringConvertible { 48 | /// An array of more `ASN1.Node`s 49 | case sequence(nodes: [Node]) 50 | /// An integer 51 | /// - Note: This ASN1 Encoder makes no assumptions about the sign and bit order of the integers passed in. The conversion from Integer to Data is your responsibility. 52 | case integer(data: Data) 53 | /// An objectIdentifier 54 | case objectIdentifier(data: Data) 55 | /// A null object 56 | case null 57 | /// A bitString 58 | case bitString(data: Data) 59 | /// An octetString 60 | case octetString(data: Data) 61 | 62 | var description: String { 63 | ASN1.printNode(self, level: 0) 64 | } 65 | } 66 | 67 | internal static func printNode(_ node: ASN1.Node, level: Int) -> String { 68 | var str: [String] = [] 69 | let prefix = String(repeating: "\t", count: level) 70 | switch node { 71 | case .integer(let int): 72 | str.append("\(prefix)Integer: \(int.toHexString())") 73 | case .bitString(let bs): 74 | str.append("\(prefix)BitString: \(bs.toHexString())") 75 | case .null: 76 | str.append("\(prefix)NULL") 77 | case .objectIdentifier(let oid): 78 | str.append("\(prefix)ObjectID: \(oid.toHexString())") 79 | case .octetString(let os): 80 | str.append("\(prefix)OctetString: \(os.toHexString())") 81 | case .sequence(let nodes): 82 | str.append("\(prefix)Sequence:") 83 | nodes.forEach { str.append(printNode($0, level: level + 1)) } 84 | } 85 | return str.joined(separator: "\n") 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/ASN1/ASN1Encoder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | // ASN1 Code inspired by Asn1Parser.swift from SwiftyRSA 16 | 17 | import Foundation 18 | 19 | extension ASN1 { 20 | enum Encoder { 21 | /// Encodes an ASN1Node into it's byte representation 22 | /// 23 | /// - Parameter node: The Node to encode 24 | /// - Returns: The encoded bytes as a UInt8 array 25 | /// 26 | /// - Warning: This ASN.1 encoder has only been tested to work on certain ASN.1 data structures such as DER and PEM files. Before using this encoder for another application, ensure you test it's behavior accordingly. 27 | /// - Warning: This encoder makes no assumptions regarding Integer bit layout and signage. The proper serialization of Integers is left up to the user. 28 | public static func encode(_ node: ASN1.Node) -> [UInt8] { 29 | switch node { 30 | case .integer(let integer): 31 | return IDENTIFIERS.INTERGER.bytes + self.asn1LengthPrefixed(integer.bytes) 32 | case .bitString(let bits): 33 | return IDENTIFIERS.BITSTRING.bytes + self.asn1LengthPrefixed([0x00] + bits.bytes) 34 | case .octetString(let octet): 35 | return IDENTIFIERS.OCTETSTRING.bytes + self.asn1LengthPrefixed(octet.bytes) 36 | case .null: 37 | return IDENTIFIERS.NULL.bytes 38 | case .objectIdentifier(let oid): 39 | return IDENTIFIERS.OBJECTID.bytes + self.asn1LengthPrefixed(oid.bytes) 40 | case .sequence(let nodes): 41 | return IDENTIFIERS.SEQUENCE.bytes + self.asn1LengthPrefixed( nodes.reduce(into: Array(), { partialResult, node in 42 | partialResult += encode(node) 43 | })) 44 | } 45 | } 46 | 47 | /// Calculates and returns the ASN.1 length Prefix for a chunk of data 48 | /// 49 | /// - Parameter bytes: The bytes to be length prefixed 50 | /// - Returns: The ASN.1 length Prefix for this chuck of data (excluding the passed in data) 51 | private static func asn1LengthPrefix(_ bytes: [UInt8]) -> [UInt8] { 52 | if bytes.count >= 0x80 { 53 | var lengthAsBytes = withUnsafeBytes(of: bytes.count.bigEndian, Array.init) 54 | while lengthAsBytes.first == 0 { lengthAsBytes.removeFirst() } 55 | return [0x80 + UInt8(lengthAsBytes.count)] + lengthAsBytes 56 | } else { 57 | return [UInt8(bytes.count)] 58 | } 59 | } 60 | 61 | /// Prefixes the provided bytes with the appropriate ASN.1 length prefix 62 | /// 63 | /// - Parameter bytes: The bytes to be length prefixed 64 | /// - Returns: The provided bytes with the appropriate ASN.1 length prefix prepended 65 | private static func asn1LengthPrefixed(_ bytes: [UInt8]) -> [UInt8] { 66 | self.asn1LengthPrefix(bytes) + bytes 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Authenticator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /// Message authentication code. 17 | public protocol Authenticator { 18 | /// Calculate Message Authentication Code (MAC) for message. 19 | func authenticate(_ bytes: Array) throws -> Array 20 | } 21 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BatchedCollection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | @usableFromInline 17 | struct BatchedCollectionIndex { 18 | let range: Range 19 | } 20 | 21 | extension BatchedCollectionIndex: Comparable { 22 | @usableFromInline 23 | static func == (lhs: BatchedCollectionIndex, rhs: BatchedCollectionIndex) -> Bool { 24 | lhs.range.lowerBound == rhs.range.lowerBound 25 | } 26 | 27 | @usableFromInline 28 | static func < (lhs: BatchedCollectionIndex, rhs: BatchedCollectionIndex) -> Bool { 29 | lhs.range.lowerBound < rhs.range.lowerBound 30 | } 31 | } 32 | 33 | protocol BatchedCollectionType: Collection { 34 | associatedtype Base: Collection 35 | } 36 | 37 | @usableFromInline 38 | struct BatchedCollection: Collection { 39 | let base: Base 40 | let size: Int 41 | 42 | @usableFromInline 43 | init(base: Base, size: Int) { 44 | self.base = base 45 | self.size = size 46 | } 47 | 48 | @usableFromInline 49 | typealias Index = BatchedCollectionIndex 50 | 51 | private func nextBreak(after idx: Base.Index) -> Base.Index { 52 | self.base.index(idx, offsetBy: self.size, limitedBy: self.base.endIndex) ?? self.base.endIndex 53 | } 54 | 55 | @usableFromInline 56 | var startIndex: Index { 57 | Index(range: self.base.startIndex.. Index { 67 | Index(range: idx.range.upperBound.. Base.SubSequence { 72 | self.base[idx.range] 73 | } 74 | } 75 | 76 | extension Collection { 77 | @inlinable 78 | func batched(by size: Int) -> BatchedCollection { 79 | BatchedCollection(base: self, size: size) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Bit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public enum Bit: Int { 17 | case zero 18 | case one 19 | } 20 | 21 | extension Bit { 22 | @inlinable 23 | func inverted() -> Bit { 24 | self == .zero ? .one : .zero 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockCipher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | protocol BlockCipher: Cipher { 17 | static var blockSize: Int { get } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockEncryptor.swift: -------------------------------------------------------------------------------- 1 | // CryptoSwift 2 | // 3 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 4 | // This software is provided 'as-is', without any express or implied warranty. 5 | // 6 | // In no event will the authors be held liable for any damages arising from the use of this software. 7 | // 8 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | // 10 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 11 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | // - This notice may not be removed or altered from any source or binary distribution. 13 | // 14 | 15 | @usableFromInline 16 | final class BlockEncryptor: Cryptor, Updatable { 17 | 18 | public enum Error: Swift.Error { 19 | case unsupported 20 | } 21 | 22 | private let blockSize: Int 23 | private var worker: CipherModeWorker 24 | private let padding: Padding 25 | // Accumulated bytes. Not all processed bytes. 26 | private var accumulated = Array(reserveCapacity: 16) 27 | 28 | private var lastBlockRemainder = 0 29 | 30 | @usableFromInline 31 | init(blockSize: Int, padding: Padding, _ worker: CipherModeWorker) throws { 32 | self.blockSize = blockSize 33 | self.padding = padding 34 | self.worker = worker 35 | } 36 | 37 | // MARK: Updatable 38 | 39 | public func update(withBytes bytes: ArraySlice, isLast: Bool) throws -> Array { 40 | self.accumulated += bytes 41 | 42 | if isLast { 43 | self.accumulated = self.padding.add(to: self.accumulated, blockSize: self.blockSize) 44 | } 45 | 46 | var encrypted = Array(reserveCapacity: accumulated.count) 47 | for chunk in self.accumulated.batched(by: self.blockSize) { 48 | if isLast || chunk.count == self.blockSize { 49 | encrypted += self.worker.encrypt(block: chunk) 50 | } 51 | } 52 | 53 | // Stream encrypts all, so it removes all elements 54 | self.accumulated.removeFirst(encrypted.count) 55 | 56 | if var finalizingWorker = worker as? FinalizingEncryptModeWorker, isLast == true { 57 | encrypted = Array(try finalizingWorker.finalize(encrypt: encrypted.slice)) 58 | } 59 | 60 | return encrypted 61 | } 62 | 63 | @usableFromInline 64 | func seek(to: Int) throws { 65 | throw Error.unsupported 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/BlockMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public typealias CipherOperationOnBlock = (_ block: ArraySlice) -> Array? 17 | 18 | public protocol BlockMode { 19 | var options: BlockModeOption { get } 20 | //TODO: doesn't have to be public 21 | @inlinable func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock, encryptionOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker 22 | 23 | var customBlockSize: Int? { get } 24 | } 25 | 26 | typealias StreamMode = BlockMode 27 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/BlockModeOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public struct BlockModeOption: OptionSet { 17 | public let rawValue: Int 18 | 19 | public init(rawValue: Int) { 20 | self.rawValue = rawValue 21 | } 22 | 23 | @usableFromInline 24 | static let none = BlockModeOption(rawValue: 1 << 0) 25 | 26 | @usableFromInline 27 | static let initializationVectorRequired = BlockModeOption(rawValue: 1 << 1) 28 | 29 | @usableFromInline 30 | static let paddingRequired = BlockModeOption(rawValue: 1 << 2) 31 | 32 | @usableFromInline 33 | static let useEncryptToDecrypt = BlockModeOption(rawValue: 1 << 3) 34 | } 35 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/CBC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // Cipher-block chaining (CBC) 17 | // 18 | 19 | public struct CBC: BlockMode { 20 | public enum Error: Swift.Error { 21 | /// Invalid IV 22 | case invalidInitializationVector 23 | } 24 | 25 | public let options: BlockModeOption = [.initializationVectorRequired, .paddingRequired] 26 | 27 | private let iv: Array 28 | 29 | public let customBlockSize: Int? = nil 30 | 31 | public init(iv: Array) { 32 | self.iv = iv 33 | } 34 | 35 | public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock, encryptionOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker { 36 | if self.iv.count != blockSize { 37 | throw Error.invalidInitializationVector 38 | } 39 | 40 | return CBCModeWorker(blockSize: blockSize, iv: self.iv.slice, cipherOperation: cipherOperation) 41 | } 42 | } 43 | 44 | struct CBCModeWorker: BlockModeWorker { 45 | let cipherOperation: CipherOperationOnBlock 46 | var blockSize: Int 47 | let additionalBufferSize: Int = 0 48 | private let iv: ArraySlice 49 | private var prev: ArraySlice? 50 | 51 | @inlinable 52 | init(blockSize: Int, iv: ArraySlice, cipherOperation: @escaping CipherOperationOnBlock) { 53 | self.blockSize = blockSize 54 | self.iv = iv 55 | self.cipherOperation = cipherOperation 56 | } 57 | 58 | @inlinable 59 | mutating func encrypt(block plaintext: ArraySlice) -> Array { 60 | guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else { 61 | return Array(plaintext) 62 | } 63 | self.prev = ciphertext.slice 64 | return ciphertext 65 | } 66 | 67 | @inlinable 68 | mutating func decrypt(block ciphertext: ArraySlice) -> Array { 69 | guard let plaintext = cipherOperation(ciphertext) else { 70 | return Array(ciphertext) 71 | } 72 | let result: Array = xor(prev ?? self.iv, plaintext) 73 | self.prev = ciphertext 74 | return result 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/CipherModeWorker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public protocol CipherModeWorker { 17 | var cipherOperation: CipherOperationOnBlock { get } 18 | 19 | // Additional space needed when incrementally process data 20 | // eg. for GCM combined mode 21 | var additionalBufferSize: Int { get } 22 | 23 | @inlinable 24 | mutating func encrypt(block plaintext: ArraySlice) -> Array 25 | 26 | @inlinable 27 | mutating func decrypt(block ciphertext: ArraySlice) -> Array 28 | } 29 | 30 | /// Block workers use `BlockEncryptor` 31 | public protocol BlockModeWorker: CipherModeWorker { 32 | var blockSize: Int { get } 33 | } 34 | 35 | public protocol CounterModeWorker: CipherModeWorker { 36 | associatedtype Counter 37 | var counter: Counter { get set } 38 | } 39 | 40 | public protocol SeekableModeWorker: CipherModeWorker { 41 | mutating func seek(to position: Int) throws 42 | } 43 | 44 | /// Stream workers use `StreamEncryptor` 45 | public protocol StreamModeWorker: CipherModeWorker { 46 | } 47 | 48 | public protocol FinalizingEncryptModeWorker: CipherModeWorker { 49 | // Any final calculations, eg. calculate tag 50 | // Called after the last block is encrypted 51 | mutating func finalize(encrypt ciphertext: ArraySlice) throws -> ArraySlice 52 | } 53 | 54 | public protocol FinalizingDecryptModeWorker: CipherModeWorker { 55 | // Called before decryption, hence input is ciphertext. 56 | // ciphertext is either a last block, or a tag (for stream workers) 57 | @discardableResult 58 | mutating func willDecryptLast(bytes ciphertext: ArraySlice) throws -> ArraySlice 59 | // Called after decryption, hence input is ciphertext 60 | mutating func didDecryptLast(bytes plaintext: ArraySlice) throws -> ArraySlice 61 | // Any final calculations, eg. calculate tag 62 | // Called after the last block is encrypted 63 | mutating func finalize(decrypt plaintext: ArraySlice) throws -> ArraySlice 64 | } 65 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/ECB.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // Electronic codebook (ECB) 17 | // 18 | 19 | public struct ECB: BlockMode { 20 | public let options: BlockModeOption = .paddingRequired 21 | public let customBlockSize: Int? = nil 22 | 23 | public init() { 24 | } 25 | 26 | public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock, encryptionOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker { 27 | ECBModeWorker(blockSize: blockSize, cipherOperation: cipherOperation) 28 | } 29 | } 30 | 31 | struct ECBModeWorker: BlockModeWorker { 32 | typealias Element = Array 33 | let cipherOperation: CipherOperationOnBlock 34 | let blockSize: Int 35 | let additionalBufferSize: Int = 0 36 | 37 | init(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) { 38 | self.blockSize = blockSize 39 | self.cipherOperation = cipherOperation 40 | } 41 | 42 | @inlinable 43 | mutating func encrypt(block plaintext: ArraySlice) -> Array { 44 | guard let ciphertext = cipherOperation(plaintext) else { 45 | return Array(plaintext) 46 | } 47 | return ciphertext 48 | } 49 | 50 | mutating func decrypt(block ciphertext: ArraySlice) -> Array { 51 | self.encrypt(block: ciphertext) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/OFB.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // Output Feedback (OFB) 17 | // 18 | 19 | public struct OFB: BlockMode { 20 | public enum Error: Swift.Error { 21 | /// Invalid IV 22 | case invalidInitializationVector 23 | } 24 | 25 | public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt] 26 | private let iv: Array 27 | public let customBlockSize: Int? = nil 28 | 29 | public init(iv: Array) { 30 | self.iv = iv 31 | } 32 | 33 | public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock, encryptionOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker { 34 | if self.iv.count != blockSize { 35 | throw Error.invalidInitializationVector 36 | } 37 | 38 | return OFBModeWorker(blockSize: blockSize, iv: self.iv.slice, cipherOperation: cipherOperation) 39 | } 40 | } 41 | 42 | struct OFBModeWorker: BlockModeWorker { 43 | let cipherOperation: CipherOperationOnBlock 44 | let blockSize: Int 45 | let additionalBufferSize: Int = 0 46 | private let iv: ArraySlice 47 | private var prev: ArraySlice? 48 | 49 | init(blockSize: Int, iv: ArraySlice, cipherOperation: @escaping CipherOperationOnBlock) { 50 | self.blockSize = blockSize 51 | self.iv = iv 52 | self.cipherOperation = cipherOperation 53 | } 54 | 55 | @inlinable 56 | mutating func encrypt(block plaintext: ArraySlice) -> Array { 57 | guard let ciphertext = cipherOperation(prev ?? iv) else { 58 | return Array(plaintext) 59 | } 60 | self.prev = ciphertext.slice 61 | return xor(plaintext, ciphertext) 62 | } 63 | 64 | @inlinable 65 | mutating func decrypt(block ciphertext: ArraySlice) -> Array { 66 | guard let decrypted = cipherOperation(prev ?? iv) else { 67 | return Array(ciphertext) 68 | } 69 | let plaintext: Array = xor(decrypted, ciphertext) 70 | prev = decrypted.slice 71 | return plaintext 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/BlockMode/PCBC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // Propagating Cipher Block Chaining (PCBC) 17 | // 18 | 19 | public struct PCBC: BlockMode { 20 | public enum Error: Swift.Error { 21 | /// Invalid IV 22 | case invalidInitializationVector 23 | } 24 | 25 | public let options: BlockModeOption = [.initializationVectorRequired, .paddingRequired] 26 | private let iv: Array 27 | public let customBlockSize: Int? = nil 28 | 29 | public init(iv: Array) { 30 | self.iv = iv 31 | } 32 | 33 | public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock, encryptionOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker { 34 | if self.iv.count != blockSize { 35 | throw Error.invalidInitializationVector 36 | } 37 | 38 | return PCBCModeWorker(blockSize: blockSize, iv: self.iv.slice, cipherOperation: cipherOperation) 39 | } 40 | } 41 | 42 | struct PCBCModeWorker: BlockModeWorker { 43 | let cipherOperation: CipherOperationOnBlock 44 | var blockSize: Int 45 | let additionalBufferSize: Int = 0 46 | private let iv: ArraySlice 47 | private var prev: ArraySlice? 48 | 49 | @inlinable 50 | init(blockSize: Int, iv: ArraySlice, cipherOperation: @escaping CipherOperationOnBlock) { 51 | self.blockSize = blockSize 52 | self.iv = iv 53 | self.cipherOperation = cipherOperation 54 | } 55 | 56 | @inlinable 57 | mutating func encrypt(block plaintext: ArraySlice) -> Array { 58 | guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else { 59 | return Array(plaintext) 60 | } 61 | self.prev = xor(plaintext, ciphertext.slice) 62 | return ciphertext 63 | } 64 | 65 | @inlinable 66 | mutating func decrypt(block ciphertext: ArraySlice) -> Array { 67 | guard let plaintext = cipherOperation(ciphertext) else { 68 | return Array(ciphertext) 69 | } 70 | let result: Array = xor(prev ?? self.iv, plaintext) 71 | self.prev = xor(result, ciphertext) 72 | return result 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CBCMAC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public final class CBCMAC: CMAC { 17 | public override func authenticate(_ bytes: Array) throws -> Array { 18 | var inBytes = bytes 19 | bitPadding(to: &inBytes, blockSize: CMAC.BlockSize) 20 | let blocks = inBytes.batched(by: CMAC.BlockSize) 21 | 22 | var lastBlockEncryptionResult: [UInt8] = CBCMAC.Zero 23 | try blocks.forEach { block in 24 | let aes = try AES(key: Array(key), blockMode: CBC(iv: lastBlockEncryptionResult), padding: .noPadding) 25 | lastBlockEncryptionResult = try aes.encrypt(block) 26 | } 27 | 28 | return lastBlockEncryptionResult 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/BigInt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CS.BigInt.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2015-12-27. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | //MARK: CS.BigInt 10 | 11 | extension CS { 12 | 13 | /// An arbitrary precision signed integer type, also known as a "big integer". 14 | /// 15 | /// Operations on big integers never overflow, but they might take a long time to execute. 16 | /// The amount of memory (and address space) available is the only constraint to the magnitude of these numbers. 17 | /// 18 | /// This particular big integer type uses base-2^64 digits to represent integers. 19 | /// 20 | /// `BigInt` is essentially a tiny wrapper that extends `BigUInt` with a sign bit and provides signed integer 21 | /// operations. Both the underlying absolute value and the negative/positive flag are available as read-write 22 | /// properties. 23 | /// 24 | /// Not all algorithms of `BigUInt` are available for `BigInt` values; for example, there is no square root or 25 | /// primality test for signed integers. When you need to call one of these, just extract the absolute value: 26 | /// 27 | /// ```Swift 28 | /// CS.BigInt(255).abs.isPrime() // Returns false 29 | /// ``` 30 | /// 31 | public struct BigInt: SignedInteger { 32 | public enum Sign { 33 | case plus 34 | case minus 35 | } 36 | 37 | public typealias Magnitude = BigUInt 38 | 39 | /// The type representing a digit in `BigInt`'s underlying number system. 40 | public typealias Word = BigUInt.Word 41 | 42 | public static var isSigned: Bool { 43 | return true 44 | } 45 | 46 | /// The absolute value of this integer. 47 | public var magnitude: BigUInt 48 | 49 | /// True iff the value of this integer is negative. 50 | public var sign: Sign 51 | 52 | /// Initializes a new big integer with the provided absolute number and sign flag. 53 | public init(sign: Sign, magnitude: BigUInt) { 54 | self.sign = (magnitude.isZero ? .plus : sign) 55 | self.magnitude = magnitude 56 | } 57 | 58 | /// Return true iff this integer is zero. 59 | /// 60 | /// - Complexity: O(1) 61 | public var isZero: Bool { 62 | return magnitude.isZero 63 | } 64 | 65 | /// Returns `-1` if this value is negative and `1` if it’s positive; otherwise, `0`. 66 | /// 67 | /// - Returns: The sign of this number, expressed as an integer of the same type. 68 | public func signum() -> CS.BigInt { 69 | switch sign { 70 | case .plus: 71 | return isZero ? 0 : 1 72 | case .minus: 73 | return -1 74 | } 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/CS.swift: -------------------------------------------------------------------------------- 1 | // CryptoSwift 2 | // 3 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 4 | // This software is provided 'as-is', without any express or implied warranty. 5 | // 6 | // In no event will the authors be held liable for any damages arising from the use of this software. 7 | // 8 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | // 10 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 11 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | // - This notice may not be removed or altered from any source or binary distribution. 13 | // 14 | 15 | // To avoid name conflict with BigInt library, I choose to rename 16 | // BigInt -> BigInteger 17 | // BigUInt -> BigUInteger 18 | 19 | public typealias BigInteger = CS.BigInt 20 | public typealias BigUInteger = CS.BigUInt 21 | 22 | public enum CS { 23 | // namespace 24 | } 25 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/Comparable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Comparable.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2016-01-03. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | import Foundation 10 | 11 | extension CS.BigUInt: Comparable { 12 | //MARK: Comparison 13 | 14 | /// Compare `a` to `b` and return an `NSComparisonResult` indicating their order. 15 | /// 16 | /// - Complexity: O(count) 17 | public static func compare(_ a: CS.BigUInt, _ b: CS.BigUInt) -> ComparisonResult { 18 | if a.count != b.count { return a.count > b.count ? .orderedDescending : .orderedAscending } 19 | for i in (0 ..< a.count).reversed() { 20 | let ad = a[i] 21 | let bd = b[i] 22 | if ad != bd { return ad > bd ? .orderedDescending : .orderedAscending } 23 | } 24 | return .orderedSame 25 | } 26 | 27 | /// Return true iff `a` is equal to `b`. 28 | /// 29 | /// - Complexity: O(count) 30 | public static func ==(a: CS.BigUInt, b: CS.BigUInt) -> Bool { 31 | return CS.BigUInt.compare(a, b) == .orderedSame 32 | } 33 | 34 | /// Return true iff `a` is less than `b`. 35 | /// 36 | /// - Complexity: O(count) 37 | public static func <(a: CS.BigUInt, b: CS.BigUInt) -> Bool { 38 | return CS.BigUInt.compare(a, b) == .orderedAscending 39 | } 40 | } 41 | 42 | extension CS.BigInt { 43 | /// Return true iff `a` is equal to `b`. 44 | public static func ==(a: CS.BigInt, b: CS.BigInt) -> Bool { 45 | return a.sign == b.sign && a.magnitude == b.magnitude 46 | } 47 | 48 | /// Return true iff `a` is less than `b`. 49 | public static func <(a: CS.BigInt, b: CS.BigInt) -> Bool { 50 | switch (a.sign, b.sign) { 51 | case (.plus, .plus): 52 | return a.magnitude < b.magnitude 53 | case (.plus, .minus): 54 | return false 55 | case (.minus, .plus): 56 | return true 57 | case (.minus, .minus): 58 | return a.magnitude > b.magnitude 59 | } 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/FloatingPointConversion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingPointConversion.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2017-08-11. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | extension CS.BigUInt { 10 | public init?(exactly source: T) { 11 | guard source.isFinite else { return nil } 12 | guard !source.isZero else { self = 0; return } 13 | guard source.sign == .plus else { return nil } 14 | let value = source.rounded(.towardZero) 15 | guard value == source else { return nil } 16 | assert(value.floatingPointClass == .positiveNormal) 17 | assert(value.exponent >= 0) 18 | let significand = value.significandBitPattern 19 | self = (CS.BigUInt(1) << value.exponent) + CS.BigUInt(significand) >> (T.significandBitCount - Int(value.exponent)) 20 | } 21 | 22 | public init(_ source: T) { 23 | self.init(exactly: source.rounded(.towardZero))! 24 | } 25 | } 26 | 27 | extension CS.BigInt { 28 | public init?(exactly source: T) { 29 | switch source.sign{ 30 | case .plus: 31 | guard let magnitude = CS.BigUInt(exactly: source) else { return nil } 32 | self = CS.BigInt(sign: .plus, magnitude: magnitude) 33 | case .minus: 34 | guard let magnitude = CS.BigUInt(exactly: -source) else { return nil } 35 | self = CS.BigInt(sign: .minus, magnitude: magnitude) 36 | } 37 | } 38 | 39 | public init(_ source: T) { 40 | self.init(exactly: source.rounded(.towardZero))! 41 | } 42 | } 43 | 44 | extension BinaryFloatingPoint where RawExponent: FixedWidthInteger, RawSignificand: FixedWidthInteger { 45 | public init(_ value: CS.BigInt) { 46 | guard !value.isZero else { self = 0; return } 47 | let v = value.magnitude 48 | let bitWidth = v.bitWidth 49 | var exponent = bitWidth - 1 50 | let shift = bitWidth - Self.significandBitCount - 1 51 | var significand = value.magnitude >> (shift - 1) 52 | if significand[0] & 3 == 3 { // Handle rounding 53 | significand >>= 1 54 | significand += 1 55 | if significand.trailingZeroBitCount >= Self.significandBitCount { 56 | exponent += 1 57 | } 58 | } 59 | else { 60 | significand >>= 1 61 | } 62 | let bias = 1 << (Self.exponentBitCount - 1) - 1 63 | guard exponent <= bias else { self = Self.infinity; return } 64 | significand &= 1 << Self.significandBitCount - 1 65 | self = Self.init(sign: value.sign == .plus ? .plus : .minus, 66 | exponentBitPattern: RawExponent(bias + exponent), 67 | significandBitPattern: RawSignificand(significand)) 68 | } 69 | 70 | public init(_ value: CS.BigUInt) { 71 | self.init(CS.BigInt(sign: .plus, magnitude: value)) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/GCD.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCD.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2016-01-03. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | extension CS.BigUInt { 10 | //MARK: Greatest Common Divisor 11 | 12 | /// Returns the greatest common divisor of `self` and `b`. 13 | /// 14 | /// - Complexity: O(count^2) where count = max(self.count, b.count) 15 | public func greatestCommonDivisor(with b: CS.BigUInt) -> CS.BigUInt { 16 | // This is Stein's algorithm: https://en.wikipedia.org/wiki/Binary_GCD_algorithm 17 | if self.isZero { return b } 18 | if b.isZero { return self } 19 | 20 | let az = self.trailingZeroBitCount 21 | let bz = b.trailingZeroBitCount 22 | let twos = Swift.min(az, bz) 23 | 24 | var (x, y) = (self >> az, b >> bz) 25 | if x < y { swap(&x, &y) } 26 | 27 | while !x.isZero { 28 | x >>= x.trailingZeroBitCount 29 | if x < y { swap(&x, &y) } 30 | x -= y 31 | } 32 | return y << twos 33 | } 34 | 35 | /// Returns the [multiplicative inverse of this integer in modulo `modulus` arithmetic][inverse], 36 | /// or `nil` if there is no such number. 37 | /// 38 | /// [inverse]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers 39 | /// 40 | /// - Returns: If `gcd(self, modulus) == 1`, the value returned is an integer `a < modulus` such that `(a * self) % modulus == 1`. If `self` and `modulus` aren't coprime, the return value is `nil`. 41 | /// - Requires: modulus > 1 42 | /// - Complexity: O(count^3) 43 | public func inverse(_ modulus: CS.BigUInt) -> CS.BigUInt? { 44 | precondition(modulus > 1) 45 | var t1 = CS.BigInt(0) 46 | var t2 = CS.BigInt(1) 47 | var r1 = modulus 48 | var r2 = self 49 | while !r2.isZero { 50 | let quotient = r1 / r2 51 | (t1, t2) = (t2, t1 - CS.BigInt(quotient) * t2) 52 | (r1, r2) = (r2, r1 - quotient * r2) 53 | } 54 | if r1 > 1 { return nil } 55 | if t1.sign == .minus { return modulus - t1.magnitude } 56 | return t1.magnitude 57 | } 58 | } 59 | 60 | extension CS.BigInt { 61 | /// Returns the greatest common divisor of `a` and `b`. 62 | /// 63 | /// - Complexity: O(count^2) where count = max(a.count, b.count) 64 | public func greatestCommonDivisor(with b: CS.BigInt) -> CS.BigInt { 65 | return CS.BigInt(self.magnitude.greatestCommonDivisor(with: b.magnitude)) 66 | } 67 | 68 | /// Returns the [multiplicative inverse of this integer in modulo `modulus` arithmetic][inverse], 69 | /// or `nil` if there is no such number. 70 | /// 71 | /// [inverse]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers 72 | /// 73 | /// - Returns: If `gcd(self, modulus) == 1`, the value returned is an integer `a < modulus` such that `(a * self) % modulus == 1`. If `self` and `modulus` aren't coprime, the return value is `nil`. 74 | /// - Requires: modulus.magnitude > 1 75 | /// - Complexity: O(count^3) 76 | public func inverse(_ modulus: CS.BigInt) -> CS.BigInt? { 77 | guard let inv = self.magnitude.inverse(modulus.magnitude) else { return nil } 78 | return CS.BigInt(self.sign == .plus || inv.isZero ? inv : modulus.magnitude - inv) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/Hashable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Hashable.swift 3 | // BigInt 4 | // 5 | // Created by Károly Lőrentey on 2016-01-03. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | extension CS.BigUInt: Hashable { 10 | //MARK: Hashing 11 | 12 | /// Append this `BigUInt` to the specified hasher. 13 | public func hash(into hasher: inout Hasher) { 14 | for word in self.words { 15 | hasher.combine(word) 16 | } 17 | } 18 | } 19 | 20 | extension CS.BigInt: Hashable { 21 | /// Append this `BigInt` to the specified hasher. 22 | public func hash(into hasher: inout Hasher) { 23 | hasher.combine(sign) 24 | hasher.combine(magnitude) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/IntegerConversion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntegerConversion.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2017-08-11. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | extension CS.BigUInt { 10 | public init?(exactly source: T) { 11 | guard source >= (0 as T) else { return nil } 12 | if source.bitWidth <= 2 * Word.bitWidth { 13 | var it = source.words.makeIterator() 14 | self.init(low: it.next() ?? 0, high: it.next() ?? 0) 15 | precondition(it.next() == nil, "Length of BinaryInteger.words is greater than its bitWidth") 16 | } 17 | else { 18 | self.init(words: source.words) 19 | } 20 | } 21 | 22 | public init(_ source: T) { 23 | precondition(source >= (0 as T), "BigUInt cannot represent negative values") 24 | self.init(exactly: source)! 25 | } 26 | 27 | public init(truncatingIfNeeded source: T) { 28 | self.init(words: source.words) 29 | } 30 | 31 | public init(clamping source: T) { 32 | if source <= (0 as T) { 33 | self.init() 34 | } 35 | else { 36 | self.init(words: source.words) 37 | } 38 | } 39 | } 40 | 41 | extension CS.BigInt { 42 | public init() { 43 | self.init(sign: .plus, magnitude: 0) 44 | } 45 | 46 | /// Initializes a new signed big integer with the same value as the specified unsigned big integer. 47 | public init(_ integer: CS.BigUInt) { 48 | self.magnitude = integer 49 | self.sign = .plus 50 | } 51 | 52 | public init(_ source: T) where T : BinaryInteger { 53 | if source >= (0 as T) { 54 | self.init(sign: .plus, magnitude: CS.BigUInt(source)) 55 | } 56 | else { 57 | var words = Array(source.words) 58 | words.twosComplement() 59 | self.init(sign: .minus, magnitude: CS.BigUInt(words: words)) 60 | } 61 | } 62 | 63 | public init?(exactly source: T) where T : BinaryInteger { 64 | self.init(source) 65 | } 66 | 67 | public init(clamping source: T) where T : BinaryInteger { 68 | self.init(source) 69 | } 70 | 71 | public init(truncatingIfNeeded source: T) where T : BinaryInteger { 72 | self.init(source) 73 | } 74 | } 75 | 76 | extension CS.BigUInt: ExpressibleByIntegerLiteral { 77 | /// Initialize a new big integer from an integer literal. 78 | public init(integerLiteral value: UInt64) { 79 | self.init(value) 80 | } 81 | } 82 | 83 | extension CS.BigInt: ExpressibleByIntegerLiteral { 84 | /// Initialize a new big integer from an integer literal. 85 | public init(integerLiteral value: Int64) { 86 | self.init(value) 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/SquareRoot.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SquareRoot.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2016-01-03. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | //MARK: Square Root 10 | 11 | extension CS.BigUInt { 12 | /// Returns the integer square root of a big integer; i.e., the largest integer whose square isn't greater than `value`. 13 | /// 14 | /// - Returns: floor(sqrt(self)) 15 | public func squareRoot() -> CS.BigUInt { 16 | // This implementation uses Newton's method. 17 | guard !self.isZero else { return CS.BigUInt() } 18 | var x = CS.BigUInt(1) << ((self.bitWidth + 1) / 2) 19 | var y: CS.BigUInt = 0 20 | while true { 21 | y.load(self) 22 | y /= x 23 | y += x 24 | y >>= 1 25 | if x == y || x == y - 1 { break } 26 | x = y 27 | } 28 | return x 29 | } 30 | } 31 | 32 | extension CS.BigInt { 33 | /// Returns the integer square root of a big integer; i.e., the largest integer whose square isn't greater than `value`. 34 | /// 35 | /// - Requires: self >= 0 36 | /// - Returns: floor(sqrt(self)) 37 | public func squareRoot() -> CS.BigInt { 38 | precondition(self.sign == .plus) 39 | return CS.BigInt(sign: .plus, magnitude: self.magnitude.squareRoot()) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CS_BigInt/Strideable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Strideable.swift 3 | // CS.BigInt 4 | // 5 | // Created by Károly Lőrentey on 2017-08-11. 6 | // Copyright © 2016-2017 Károly Lőrentey. 7 | // 8 | 9 | extension CS.BigUInt: Strideable { 10 | /// A type that can represent the distance between two values ofa `BigUInt`. 11 | public typealias Stride = CS.BigInt 12 | 13 | /// Adds `n` to `self` and returns the result. Traps if the result would be less than zero. 14 | public func advanced(by n: CS.BigInt) -> CS.BigUInt { 15 | return n.sign == .minus ? self - n.magnitude : self + n.magnitude 16 | } 17 | 18 | /// Returns the (potentially negative) difference between `self` and `other` as a `BigInt`. Never traps. 19 | public func distance(to other: CS.BigUInt) -> CS.BigInt { 20 | return CS.BigInt(other) - CS.BigInt(self) 21 | } 22 | } 23 | 24 | extension CS.BigInt: Strideable { 25 | public typealias Stride = CS.BigInt 26 | 27 | /// Returns `self + n`. 28 | public func advanced(by n: Stride) -> CS.BigInt { 29 | return self + n 30 | } 31 | 32 | /// Returns `other - self`. 33 | public func distance(to other: CS.BigInt) -> Stride { 34 | return other - self 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Cipher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public enum CipherError: Error { 17 | case encrypt 18 | case decrypt 19 | } 20 | 21 | public protocol Cipher: AnyObject { 22 | var keySize: Int { get } 23 | 24 | /// Encrypt given bytes at once 25 | /// 26 | /// - parameter bytes: Plaintext data 27 | /// - returns: Encrypted data 28 | func encrypt(_ bytes: ArraySlice) throws -> Array 29 | func encrypt(_ bytes: Array) throws -> Array 30 | 31 | /// Decrypt given bytes at once 32 | /// 33 | /// - parameter bytes: Ciphertext data 34 | /// - returns: Plaintext data 35 | func decrypt(_ bytes: ArraySlice) throws -> Array 36 | func decrypt(_ bytes: Array) throws -> Array 37 | } 38 | 39 | extension Cipher { 40 | public func encrypt(_ bytes: Array) throws -> Array { 41 | try self.encrypt(bytes.slice) 42 | } 43 | 44 | public func decrypt(_ bytes: Array) throws -> Array { 45 | try self.decrypt(bytes.slice) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Collection+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | extension Collection where Self.Element == UInt8, Self.Index == Int { 16 | // Big endian order 17 | @inlinable 18 | func toUInt32Array() -> Array { 19 | guard !isEmpty else { 20 | return [] 21 | } 22 | 23 | let c = strideCount(from: startIndex, to: endIndex, by: 4) 24 | return Array(unsafeUninitializedCapacity: c) { buf, count in 25 | var counter = 0 26 | for idx in stride(from: startIndex, to: endIndex, by: 4) { 27 | let val = UInt32(bytes: self, fromIndex: idx).bigEndian 28 | buf[counter] = val 29 | counter += 1 30 | } 31 | count = counter 32 | assert(counter == c) 33 | } 34 | } 35 | 36 | // Big endian order 37 | @inlinable 38 | func toUInt64Array() -> Array { 39 | guard !isEmpty else { 40 | return [] 41 | } 42 | 43 | let c = strideCount(from: startIndex, to: endIndex, by: 8) 44 | return Array(unsafeUninitializedCapacity: c) { buf, count in 45 | var counter = 0 46 | for idx in stride(from: startIndex, to: endIndex, by: 8) { 47 | let val = UInt64(bytes: self, fromIndex: idx).bigEndian 48 | buf[counter] = val 49 | counter += 1 50 | } 51 | count = counter 52 | assert(counter == c) 53 | } 54 | } 55 | } 56 | 57 | @usableFromInline 58 | func strideCount(from: Int, to: Int, by: Int) -> Int { 59 | let count = to - from 60 | return count / by + (count % by > 0 ? 1 : 0) 61 | } 62 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/CompactMap.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #if swift(>=4.1) 17 | // TODO: remove this file when Xcode 9.2 is no longer used 18 | #else 19 | extension Sequence { 20 | @inlinable 21 | public func compactMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] { 22 | try flatMap(transform) 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Cryptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /// Cryptor (Encryptor or Decryptor) 17 | public protocol Cryptor { 18 | /// Seek to position in file, if block mode allows random access. 19 | /// 20 | /// - parameter to: new value of counter 21 | mutating func seek(to: Int) throws 22 | } 23 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Cryptors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #if canImport(Darwin) 17 | import Darwin 18 | #elseif canImport(Android) 19 | import Android 20 | #elseif canImport(Glibc) 21 | import Glibc 22 | #elseif canImport(Musl) 23 | import Musl 24 | #elseif canImport(ucrt) 25 | import ucrt 26 | #endif 27 | 28 | /// Worker cryptor/decryptor of `Updatable` types 29 | public protocol Cryptors: AnyObject { 30 | 31 | /// Cryptor suitable for encryption 32 | func makeEncryptor() throws -> Cryptor & Updatable 33 | 34 | /// Cryptor suitable for decryption 35 | func makeDecryptor() throws -> Cryptor & Updatable 36 | 37 | /// Generate array of random bytes. Helper function. 38 | static func randomIV(_ blockSize: Int) -> Array 39 | } 40 | 41 | extension Cryptors { 42 | /// Generate array of random values. 43 | /// Convenience helper that uses `Swift.RandomNumberGenerator`. 44 | /// - Parameter count: Length of array 45 | public static func randomIV(_ count: Int) -> Array { 46 | (0.. 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | @available(*, renamed: "Digest") 17 | public typealias Hash = Digest 18 | 19 | /// Hash functions to calculate Digest. 20 | public struct Digest { 21 | /// Calculate MD5 Digest 22 | /// - parameter bytes: input message 23 | /// - returns: Digest bytes 24 | public static func md5(_ bytes: Array) -> Array { 25 | MD5().calculate(for: bytes) 26 | } 27 | 28 | /// Calculate SHA1 Digest 29 | /// - parameter bytes: input message 30 | /// - returns: Digest bytes 31 | public static func sha1(_ bytes: Array) -> Array { 32 | SHA1().calculate(for: bytes) 33 | } 34 | 35 | /// Calculate SHA2-224 Digest 36 | /// - parameter bytes: input message 37 | /// - returns: Digest bytes 38 | public static func sha224(_ bytes: Array) -> Array { 39 | self.sha2(bytes, variant: .sha224) 40 | } 41 | 42 | /// Calculate SHA2-256 Digest 43 | /// - parameter bytes: input message 44 | /// - returns: Digest bytes 45 | public static func sha256(_ bytes: Array) -> Array { 46 | self.sha2(bytes, variant: .sha256) 47 | } 48 | 49 | /// Calculate SHA2-384 Digest 50 | /// - parameter bytes: input message 51 | /// - returns: Digest bytes 52 | public static func sha384(_ bytes: Array) -> Array { 53 | self.sha2(bytes, variant: .sha384) 54 | } 55 | 56 | /// Calculate SHA2-512 Digest 57 | /// - parameter bytes: input message 58 | /// - returns: Digest bytes 59 | public static func sha512(_ bytes: Array) -> Array { 60 | self.sha2(bytes, variant: .sha512) 61 | } 62 | 63 | /// Calculate SHA2 Digest 64 | /// - parameter bytes: input message 65 | /// - parameter variant: SHA-2 variant 66 | /// - returns: Digest bytes 67 | public static func sha2(_ bytes: Array, variant: SHA2.Variant) -> Array { 68 | SHA2(variant: variant).calculate(for: bytes) 69 | } 70 | 71 | /// Calculate SHA3 Digest 72 | /// - parameter bytes: input message 73 | /// - parameter variant: SHA-3 variant 74 | /// - returns: Digest bytes 75 | public static func sha3(_ bytes: Array, variant: SHA3.Variant) -> Array { 76 | SHA3(variant: variant).calculate(for: bytes) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/DigestType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | internal protocol DigestType { 17 | func calculate(for bytes: Array) -> Array 18 | } 19 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/AES+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension AES { 19 | /// Initialize with CBC block mode. 20 | /// 21 | /// - Parameters: 22 | /// - key: Key as a String. 23 | /// - iv: IV as a String. 24 | /// - padding: Padding 25 | /// - Throws: Error 26 | /// 27 | /// The input is a String, that is treat as sequence of bytes made directly out of String. 28 | /// If input is Base64 encoded data (which is a String technically) it is not decoded automatically for you. 29 | public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws { 30 | try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/Array+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | public extension Array where Element == UInt8 { 19 | func toBase64(options: Data.Base64EncodingOptions = []) -> String { 20 | Data(self).base64EncodedString(options: options) 21 | } 22 | 23 | init(base64: String, options: Data.Base64DecodingOptions = .ignoreUnknownCharacters) { 24 | self.init() 25 | 26 | guard let decodedData = Data(base64Encoded: base64, options: options) else { 27 | return 28 | } 29 | 30 | append(contentsOf: decodedData.bytes) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension Blowfish { 19 | /// Initialize with CBC block mode. 20 | public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws { 21 | try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension ChaCha20 { 19 | public convenience init(key: String, iv: String) throws { 20 | try self.init(key: key.bytes, iv: iv.bytes) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/Data+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension Data { 19 | /// Two octet checksum as defined in RFC-4880. Sum of all octets, mod 65536 20 | public func checksum() -> UInt16 { 21 | let s = self.withUnsafeBytes { buf in 22 | return buf.lazy.map(UInt32.init).reduce(UInt32(0), +) 23 | } 24 | return UInt16(s % 65535) 25 | } 26 | 27 | public func md5() -> Data { 28 | Data( Digest.md5(bytes)) 29 | } 30 | 31 | public func sha1() -> Data { 32 | Data( Digest.sha1(bytes)) 33 | } 34 | 35 | public func sha224() -> Data { 36 | Data( Digest.sha224(bytes)) 37 | } 38 | 39 | public func sha256() -> Data { 40 | Data( Digest.sha256(bytes)) 41 | } 42 | 43 | public func sha384() -> Data { 44 | Data( Digest.sha384(bytes)) 45 | } 46 | 47 | public func sha512() -> Data { 48 | Data( Digest.sha512(bytes)) 49 | } 50 | 51 | public func sha3(_ variant: SHA3.Variant) -> Data { 52 | Data( Digest.sha3(bytes, variant: variant)) 53 | } 54 | 55 | public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> Data { 56 | Data( Checksum.crc32(bytes, seed: seed, reflect: reflect).bytes()) 57 | } 58 | 59 | public func crc32c(seed: UInt32? = nil, reflect: Bool = true) -> Data { 60 | Data( Checksum.crc32c(bytes, seed: seed, reflect: reflect).bytes()) 61 | } 62 | 63 | public func crc16(seed: UInt16? = nil) -> Data { 64 | Data( Checksum.crc16(bytes, seed: seed).bytes()) 65 | } 66 | 67 | public func encrypt(cipher: Cipher) throws -> Data { 68 | Data( try cipher.encrypt(bytes.slice)) 69 | } 70 | 71 | public func decrypt(cipher: Cipher) throws -> Data { 72 | Data( try cipher.decrypt(bytes.slice)) 73 | } 74 | 75 | public func authenticate(with authenticator: Authenticator) throws -> Data { 76 | Data( try authenticator.authenticate(bytes)) 77 | } 78 | } 79 | 80 | extension Data { 81 | public init(hex: String) { 82 | self.init(Array(hex: hex)) 83 | } 84 | 85 | public var bytes: Array { 86 | Array(self) 87 | } 88 | 89 | public func toHexString() -> String { 90 | self.bytes.toHexString() 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/HMAC+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension HMAC { 19 | public convenience init(key: String, variant: HMAC.Variant = .md5) throws { 20 | self.init(key: key.bytes, variant: variant) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/Rabbit+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension Rabbit { 19 | public convenience init(key: String) throws { 20 | try self.init(key: key.bytes) 21 | } 22 | 23 | public convenience init(key: String, iv: String) throws { 24 | try self.init(key: key.bytes, iv: iv.bytes) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/String+FoundationExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension String { 19 | /// Return Base64 back to String 20 | public func decryptBase64ToString(cipher: Cipher) throws -> String { 21 | guard let decodedData = Data(base64Encoded: self, options: []) else { 22 | throw CipherError.decrypt 23 | } 24 | 25 | let decrypted = try decodedData.decrypt(cipher: cipher) 26 | 27 | if let decryptedString = String(data: decrypted, encoding: String.Encoding.utf8) { 28 | return decryptedString 29 | } 30 | 31 | throw CipherError.decrypt 32 | } 33 | 34 | public func decryptBase64(cipher: Cipher) throws -> Array { 35 | guard let decodedData = Data(base64Encoded: self, options: []) else { 36 | throw CipherError.decrypt 37 | } 38 | 39 | return try decodedData.decrypt(cipher: cipher).bytes 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/Utils+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | func perf(_ text: String, closure: () -> Void) { 19 | let measurementStart = Date() 20 | 21 | closure() 22 | 23 | let measurementStop = Date() 24 | let executionTime = measurementStop.timeIntervalSince(measurementStart) 25 | 26 | print("\(text) \(executionTime)") 27 | } 28 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Foundation/XChaCha20+Foundation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | extension XChaCha20 { 19 | /// Convenience initializer that creates an XChaCha20 instance with the given key and IV 20 | /// represented as hex-encoded strings. 21 | /// 22 | /// - Parameters: 23 | /// - key: The encryption/decryption key as a hex-encoded string. 24 | /// - iv: The initialization vector as a hex-encoded string. 25 | /// - Throws: An error if the provided key or IV are of invalid length, format, or not hex-encoded. 26 | public convenience init(key: String, iv: String) throws { 27 | try self.init(key: key.bytes, iv: iv.bytes) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Generics.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /// Array of bytes. Caution: don't use directly because generic is slow. 17 | /// 18 | /// - parameter value: integer value 19 | /// - parameter length: length of output array. By default size of value type 20 | /// 21 | /// - returns: Array of bytes 22 | @_specialize(where T == Int) 23 | @_specialize(where T == UInt) 24 | @_specialize(where T == UInt8) 25 | @_specialize(where T == UInt16) 26 | @_specialize(where T == UInt32) 27 | @_specialize(where T == UInt64) 28 | @inlinable 29 | func arrayOfBytes(value: T, length totalBytes: Int = MemoryLayout.size) -> Array { 30 | let valuePointer = UnsafeMutablePointer.allocate(capacity: 1) 31 | valuePointer.pointee = value 32 | 33 | let bytesPointer = UnsafeMutablePointer(OpaquePointer(valuePointer)) 34 | var bytes = Array(repeating: 0, count: totalBytes) 35 | for j in 0...size, totalBytes) { 36 | bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee 37 | } 38 | 39 | valuePointer.deinitialize(count: 1) 40 | valuePointer.deallocate() 41 | 42 | return bytes 43 | } 44 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/HKDF.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // https://www.ietf.org/rfc/rfc5869.txt 17 | // 18 | 19 | #if canImport(Darwin) 20 | import Darwin 21 | #elseif canImport(Android) 22 | import Android 23 | #elseif canImport(Glibc) 24 | import Glibc 25 | #elseif canImport(Musl) 26 | import Musl 27 | #elseif canImport(ucrt) 28 | import ucrt 29 | #elseif canImport(WASILibc) 30 | import WASILibc 31 | #endif 32 | 33 | /// A key derivation function. 34 | /// 35 | /// HKDF - HMAC-based Extract-and-Expand Key Derivation Function. 36 | public struct HKDF { 37 | public enum Error: Swift.Error { 38 | case invalidInput 39 | case derivedKeyTooLong 40 | } 41 | 42 | private let numBlocks: Int // l 43 | private let dkLen: Int 44 | private let info: Array 45 | private let prk: Array 46 | private let variant: HMAC.Variant 47 | 48 | /// - parameters: 49 | /// - variant: hash variant 50 | /// - salt: optional salt (if not provided, it is set to a sequence of variant.digestLength zeros) 51 | /// - info: optional context and application specific information 52 | /// - keyLength: intended length of derived key 53 | public init(password: Array, salt: Array? = nil, info: Array? = nil, keyLength: Int? = nil /* dkLen */, variant: HMAC.Variant = .sha2(.sha256)) throws { 54 | guard !password.isEmpty else { 55 | throw Error.invalidInput 56 | } 57 | 58 | let dkLen = keyLength ?? variant.digestLength 59 | let keyLengthFinal = Double(dkLen) 60 | let hLen = Double(variant.digestLength) 61 | let numBlocks = Int(ceil(keyLengthFinal / hLen)) // l = ceil(keyLength / hLen) 62 | guard numBlocks <= 255 else { 63 | throw Error.derivedKeyTooLong 64 | } 65 | 66 | /// HKDF-Extract(salt, password) -> PRK 67 | /// - PRK - a pseudo-random key; it is used by calculate() 68 | self.prk = try HMAC(key: salt ?? [], variant: variant).authenticate(password) 69 | self.info = info ?? [] 70 | self.variant = variant 71 | self.dkLen = dkLen 72 | self.numBlocks = numBlocks 73 | } 74 | 75 | public func calculate() throws -> Array { 76 | let hmac = HMAC(key: prk, variant: variant) 77 | var ret = Array() 78 | ret.reserveCapacity(self.numBlocks * self.variant.digestLength) 79 | var value = Array() 80 | for i in 1...self.numBlocks { 81 | value.append(contentsOf: self.info) 82 | value.append(UInt8(i)) 83 | 84 | let bytes = try hmac.authenticate(value) 85 | ret.append(contentsOf: bytes) 86 | 87 | /// update value to use it as input for next iteration 88 | value = bytes 89 | } 90 | return Array(ret.prefix(self.dkLen)) 91 | } 92 | 93 | public func callAsFunction() throws -> Array { 94 | try calculate() 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/ISO10126Padding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | /// Padding with random bytes, ending with the number of added bytes. 19 | /// Read the [Wikipedia](https://en.wikipedia.org/wiki/Padding_(cryptography)#ISO_10126) 20 | /// and [Crypto-IT](http://www.crypto-it.net/eng/theory/padding.html) articles for more info. 21 | struct ISO10126Padding: PaddingProtocol { 22 | init() { 23 | } 24 | 25 | @inlinable 26 | func add(to bytes: Array, blockSize: Int) -> Array { 27 | let padding = UInt8(blockSize - (bytes.count % blockSize)) 28 | var withPadding = bytes 29 | if padding > 0 { 30 | withPadding += (0..<(padding - 1)).map { _ in UInt8.random(in: 0...255) } + [padding] 31 | } 32 | return withPadding 33 | } 34 | 35 | @inlinable 36 | func remove(from bytes: Array, blockSize: Int?) -> Array { 37 | guard !bytes.isEmpty, let lastByte = bytes.last else { 38 | return bytes 39 | } 40 | 41 | assert(!bytes.isEmpty, "Need bytes to remove padding") 42 | 43 | let padding = Int(lastByte) // last byte 44 | let finalLength = bytes.count - padding 45 | 46 | if finalLength < 0 { 47 | return bytes 48 | } 49 | 50 | if padding >= 1 { 51 | return Array(bytes[0.. 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | // First byte is 0x80, rest is zero padding 19 | // http://www.crypto-it.net/eng/theory/padding.html 20 | // http://www.embedx.com/pdfs/ISO_STD_7816/info_isoiec7816-4%7Bed21.0%7Den.pdf 21 | struct ISO78164Padding: PaddingProtocol { 22 | init() { 23 | } 24 | 25 | @inlinable 26 | func add(to bytes: Array, blockSize: Int) -> Array { 27 | var padded = Array(bytes) 28 | padded.append(0x80) 29 | 30 | while (padded.count % blockSize) != 0 { 31 | padded.append(0x00) 32 | } 33 | return padded 34 | } 35 | 36 | @inlinable 37 | func remove(from bytes: Array, blockSize _: Int?) -> Array { 38 | if let idx = bytes.lastIndex(of: 0x80) { 39 | return Array(bytes[.. 6 | // This software is provided 'as-is', without any express or implied warranty. 7 | // 8 | // In no event will the authors be held liable for any damages arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 11 | // 12 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 13 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | // - This notice may not be removed or altered from any source or binary distribution. 15 | // 16 | 17 | #if canImport(Darwin) 18 | import Darwin 19 | #elseif canImport(Android) 20 | import Android 21 | #elseif canImport(Glibc) 22 | import Glibc 23 | #elseif canImport(Musl) 24 | import Musl 25 | #elseif canImport(ucrt) 26 | import ucrt 27 | #endif 28 | 29 | extension FixedWidthInteger { 30 | @inlinable 31 | func bytes(totalBytes: Int = MemoryLayout.size) -> Array { 32 | arrayOfBytes(value: self.littleEndian, length: totalBytes) 33 | // TODO: adjust bytes order 34 | // var value = self.littleEndian 35 | // return withUnsafeBytes(of: &value, Array.init).reversed() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/NoPadding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | struct NoPadding: PaddingProtocol { 17 | init() { 18 | } 19 | 20 | func add(to data: Array, blockSize _: Int) -> Array { 21 | data 22 | } 23 | 24 | func remove(from data: Array, blockSize _: Int?) -> Array { 25 | data 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Operators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /* 17 | Bit shifting with overflow protection using overflow operator "&". 18 | Approach is consistent with standard overflow operators &+, &-, &*, &/ 19 | and introduce new overflow operators for shifting: &<<, &>> 20 | 21 | Note: Works with unsigned integers values only 22 | 23 | Usage 24 | 25 | var i = 1 // init 26 | var j = i &<< 2 //shift left 27 | j &<<= 2 //shift left and assign 28 | 29 | @see: https://medium.com/@krzyzanowskim/swiftly-shift-bits-and-protect-yourself-be33016ce071 30 | 31 | This fuctonality is now implemented as part of Swift 3, SE-0104 https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md 32 | */ 33 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/PKCS/PBKDF1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public extension PKCS5 { 17 | /// A key derivation function. 18 | /// 19 | /// PBKDF1 is recommended only for compatibility with existing 20 | /// applications since the keys it produces may not be large enough for 21 | /// some applications. 22 | struct PBKDF1 { 23 | public enum Error: Swift.Error { 24 | case invalidInput 25 | case derivedKeyTooLong 26 | } 27 | 28 | public enum Variant { 29 | case md5, sha1 30 | 31 | @usableFromInline 32 | var size: Int { 33 | switch self { 34 | case .md5: 35 | return MD5.digestLength 36 | case .sha1: 37 | return SHA1.digestLength 38 | } 39 | } 40 | 41 | @usableFromInline 42 | func calculateHash(_ bytes: Array) -> Array { 43 | switch self { 44 | case .sha1: 45 | return Digest.sha1(bytes) 46 | case .md5: 47 | return Digest.md5(bytes) 48 | } 49 | } 50 | } 51 | 52 | @usableFromInline 53 | let iterations: Int // c 54 | 55 | @usableFromInline 56 | let variant: Variant 57 | 58 | @usableFromInline 59 | let keyLength: Int 60 | 61 | @usableFromInline 62 | let t1: Array 63 | 64 | /// - parameters: 65 | /// - salt: salt, an eight-bytes 66 | /// - variant: hash variant 67 | /// - iterations: iteration count, a positive integer 68 | /// - keyLength: intended length of derived key 69 | public init(password: Array, salt: Array, variant: Variant = .sha1, iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */ ) throws { 70 | precondition(iterations > 0) 71 | precondition(salt.count == 8) 72 | 73 | let keyLength = keyLength ?? variant.size 74 | 75 | if keyLength > variant.size { 76 | throw Error.derivedKeyTooLong 77 | } 78 | 79 | let t1 = variant.calculateHash(password + salt) 80 | 81 | self.iterations = iterations 82 | self.variant = variant 83 | self.keyLength = keyLength 84 | self.t1 = t1 85 | } 86 | 87 | /// Apply the underlying hash function Hash for c iterations 88 | @inlinable 89 | public func calculate() -> Array { 90 | var t = self.t1 91 | for _ in 2...self.iterations { 92 | t = self.variant.calculateHash(t) 93 | } 94 | return Array(t[0.. Array { 98 | calculate() 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/PKCS/PKCS5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // PKCS is a group of public-key cryptography standards devised 17 | // and published by RSA Security Inc, starting in the early 1990s. 18 | // 19 | 20 | public enum PKCS5 { 21 | typealias Padding = PKCS7Padding 22 | } 23 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/PKCS/PKCS7.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public enum PKCS7 { 17 | typealias Padding = PKCS7Padding 18 | } 19 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/PKCS/PKCS7Padding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // PKCS is a group of public-key cryptography standards devised 17 | // and published by RSA Security Inc, starting in the early 1990s. 18 | // 19 | 20 | struct PKCS7Padding: PaddingProtocol { 21 | enum Error: Swift.Error { 22 | case invalidPaddingValue 23 | } 24 | 25 | init() { 26 | } 27 | 28 | @inlinable 29 | func add(to bytes: Array, blockSize: Int) -> Array { 30 | let padding = UInt8(blockSize - (bytes.count % blockSize)) 31 | // The value of each added byte is the number of bytes that are added 32 | return bytes + Array(repeating: padding, count: Int(padding)) 33 | } 34 | 35 | @inlinable 36 | func remove(from bytes: Array, blockSize _: Int?) -> Array { 37 | guard !bytes.isEmpty, let lastByte = bytes.last else { 38 | return bytes 39 | } 40 | 41 | assert(!bytes.isEmpty, "Need bytes to remove padding") 42 | 43 | let padding = Int(lastByte) // last byte 44 | let finalLength = bytes.count - padding 45 | 46 | if finalLength < 0 { 47 | return bytes 48 | } 49 | 50 | if padding >= 1 { 51 | return Array(bytes[0.. 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public protocol PaddingProtocol { 17 | func add(to: Array, blockSize: Int) -> Array 18 | func remove(from: Array, blockSize: Int?) -> Array 19 | } 20 | 21 | public enum Padding: PaddingProtocol { 22 | case noPadding, zeroPadding, pkcs7, pkcs5, eme_pkcs1v15, emsa_pkcs1v15, iso78164, iso10126 23 | 24 | public func add(to: Array, blockSize: Int) -> Array { 25 | switch self { 26 | case .noPadding: 27 | return to // NoPadding().add(to: to, blockSize: blockSize) 28 | case .zeroPadding: 29 | return ZeroPadding().add(to: to, blockSize: blockSize) 30 | case .pkcs7: 31 | return PKCS7.Padding().add(to: to, blockSize: blockSize) 32 | case .pkcs5: 33 | return PKCS5.Padding().add(to: to, blockSize: blockSize) 34 | case .eme_pkcs1v15: 35 | return EMEPKCS1v15Padding().add(to: to, blockSize: blockSize) 36 | case .emsa_pkcs1v15: 37 | return EMSAPKCS1v15Padding().add(to: to, blockSize: blockSize) 38 | case .iso78164: 39 | return ISO78164Padding().add(to: to, blockSize: blockSize) 40 | case .iso10126: 41 | return ISO10126Padding().add(to: to, blockSize: blockSize) 42 | } 43 | } 44 | 45 | public func remove(from: Array, blockSize: Int?) -> Array { 46 | switch self { 47 | case .noPadding: 48 | return from //NoPadding().remove(from: from, blockSize: blockSize) 49 | case .zeroPadding: 50 | return ZeroPadding().remove(from: from, blockSize: blockSize) 51 | case .pkcs7: 52 | return PKCS7.Padding().remove(from: from, blockSize: blockSize) 53 | case .pkcs5: 54 | return PKCS5.Padding().remove(from: from, blockSize: blockSize) 55 | case .eme_pkcs1v15: 56 | return EMEPKCS1v15Padding().remove(from: from, blockSize: blockSize) 57 | case .emsa_pkcs1v15: 58 | return EMSAPKCS1v15Padding().remove(from: from, blockSize: blockSize) 59 | case .iso78164: 60 | return ISO78164Padding().remove(from: from, blockSize: blockSize) 61 | case .iso10126: 62 | return ISO10126Padding().remove(from: from, blockSize: blockSize) 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyTrackingDomains 8 | 9 | NSPrivacyCollectedDataTypes 10 | 11 | NSPrivacyAccessedAPITypes 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/SecureBytes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #if canImport(Darwin) 17 | import Darwin 18 | #elseif canImport(Android) 19 | import Android 20 | #elseif canImport(Glibc) 21 | import Glibc 22 | #elseif canImport(Musl) 23 | import Musl 24 | #elseif canImport(WinSDK) 25 | import WinSDK 26 | #endif 27 | 28 | typealias Key = SecureBytes 29 | 30 | /// Keeps bytes in memory. Because this is class, bytes are not copied 31 | /// and memory area is locked as long as referenced, then unlocked on deinit 32 | final class SecureBytes { 33 | private let bytes: Array 34 | let count: Int 35 | 36 | init(bytes: Array) { 37 | self.bytes = bytes 38 | self.count = bytes.count 39 | self.bytes.withUnsafeBufferPointer { (pointer) -> Void in 40 | #if os(Windows) 41 | VirtualLock(UnsafeMutableRawPointer(mutating: pointer.baseAddress), SIZE_T(pointer.count)) 42 | #elseif os(WASI) 43 | // not supported on WASI 44 | #elseif os(Android) 45 | mlock(pointer.baseAddress!, pointer.count) 46 | #else 47 | mlock(pointer.baseAddress, pointer.count) 48 | #endif 49 | } 50 | } 51 | 52 | deinit { 53 | self.bytes.withUnsafeBufferPointer { (pointer) -> Void in 54 | #if os(Windows) 55 | VirtualUnlock(UnsafeMutableRawPointer(mutating: pointer.baseAddress), SIZE_T(pointer.count)) 56 | #elseif os(WASI) 57 | // not supported on WASI 58 | #elseif os(Android) 59 | munlock(pointer.baseAddress!, pointer.count) 60 | #else 61 | munlock(pointer.baseAddress, pointer.count) 62 | #endif 63 | } 64 | } 65 | } 66 | 67 | extension SecureBytes: Collection { 68 | typealias Index = Int 69 | 70 | var endIndex: Int { 71 | self.bytes.endIndex 72 | } 73 | 74 | var startIndex: Int { 75 | self.bytes.startIndex 76 | } 77 | 78 | subscript(position: Index) -> UInt8 { 79 | self.bytes[position] 80 | } 81 | 82 | subscript(bounds: Range) -> ArraySlice { 83 | self.bytes[bounds] 84 | } 85 | 86 | func formIndex(after i: inout Int) { 87 | self.bytes.formIndex(after: &i) 88 | } 89 | 90 | func index(after i: Int) -> Int { 91 | self.bytes.index(after: i) 92 | } 93 | } 94 | 95 | extension SecureBytes: ExpressibleByArrayLiteral { 96 | public convenience init(arrayLiteral elements: UInt8...) { 97 | self.init(bytes: elements) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/Signature.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | public enum SignatureError: Error { 17 | case sign 18 | case verify 19 | } 20 | 21 | public protocol Signature: AnyObject { 22 | var keySize: Int { get } 23 | 24 | /// Sign the given bytes at once 25 | /// 26 | /// - parameter bytes: Plaintext data to be signed 27 | /// - returns: The signed data 28 | func sign(_ bytes: ArraySlice) throws -> Array 29 | /// Sign the given bytes at once 30 | /// 31 | /// - parameter bytes: Plaintext data to be signed 32 | /// - returns: The signed data 33 | func sign(_ bytes: Array) throws -> Array 34 | 35 | /// Verify the given bytes against the expected data 36 | /// 37 | /// - parameter signature: Signature data 38 | /// - parameter expectedData: The original data that you expected to be signed 39 | /// - returns: `True` when the signature is valid for the expected data, `False` otherwise. 40 | func verify(signature: ArraySlice, for expectedData: ArraySlice) throws -> Bool 41 | /// Verify the given bytes against the expected data 42 | /// 43 | /// - parameter signature: Signature data 44 | /// - parameter expectedData: The original data that you expected to be signed 45 | /// - returns: `True` when the signature is valid for the expected data, `False` otherwise. 46 | func verify(signature: Array, for expectedData: Array) throws -> Bool 47 | } 48 | 49 | extension Signature { 50 | /// Sign the given bytes at once 51 | /// 52 | /// - parameter bytes: Plaintext data to be signed 53 | /// - returns: The signed data 54 | public func sign(_ bytes: Array) throws -> Array { 55 | try self.sign(bytes.slice) 56 | } 57 | 58 | /// Verify the given bytes against the expected data 59 | /// 60 | /// - parameter signature: Signature data 61 | /// - parameter expectedData: The original data that you expected to be signed 62 | /// - returns: `True` when the signature is valid for the expected data, `False` otherwise. 63 | public func verify(signature: Array, for expectedData: Array) throws -> Bool { 64 | try self.verify(signature: signature.slice, for: expectedData.slice) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/StreamDecryptor.swift: -------------------------------------------------------------------------------- 1 | // CryptoSwift 2 | // 3 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 4 | // This software is provided 'as-is', without any express or implied warranty. 5 | // 6 | // In no event will the authors be held liable for any damages arising from the use of this software. 7 | // 8 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | // 10 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 11 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | // - This notice may not be removed or altered from any source or binary distribution. 13 | // 14 | 15 | @usableFromInline 16 | final class StreamDecryptor: Cryptor, Updatable { 17 | 18 | @usableFromInline 19 | enum Error: Swift.Error { 20 | case unsupported 21 | } 22 | 23 | @usableFromInline 24 | internal let blockSize: Int 25 | 26 | @usableFromInline 27 | internal var worker: CipherModeWorker 28 | 29 | @usableFromInline 30 | internal let padding: Padding 31 | 32 | @usableFromInline 33 | internal var accumulated = Array() 34 | 35 | @usableFromInline 36 | internal var lastBlockRemainder = 0 37 | 38 | @usableFromInline 39 | init(blockSize: Int, padding: Padding, _ worker: CipherModeWorker) throws { 40 | self.blockSize = blockSize 41 | self.padding = padding 42 | self.worker = worker 43 | } 44 | 45 | // MARK: Updatable 46 | 47 | @inlinable 48 | public func update(withBytes bytes: ArraySlice, isLast: Bool) throws -> Array { 49 | self.accumulated += bytes 50 | 51 | let toProcess = self.accumulated.prefix(max(self.accumulated.count - self.worker.additionalBufferSize, 0)) 52 | 53 | if var finalizingWorker = worker as? FinalizingDecryptModeWorker, isLast == true { 54 | // will truncate suffix if needed 55 | try finalizingWorker.willDecryptLast(bytes: self.accumulated.slice) 56 | } 57 | 58 | var processedBytesCount = 0 59 | var plaintext = Array(reserveCapacity: bytes.count + self.worker.additionalBufferSize) 60 | for chunk in toProcess.batched(by: self.blockSize) { 61 | plaintext += self.worker.decrypt(block: chunk) 62 | processedBytesCount += chunk.count 63 | } 64 | 65 | if var finalizingWorker = worker as? FinalizingDecryptModeWorker, isLast == true { 66 | plaintext = Array(try finalizingWorker.didDecryptLast(bytes: plaintext.slice)) 67 | } 68 | 69 | // omit unnecessary calculation if not needed 70 | if self.padding != .noPadding { 71 | self.lastBlockRemainder = plaintext.count.quotientAndRemainder(dividingBy: self.blockSize).remainder 72 | } 73 | 74 | if isLast { 75 | // CTR doesn't need padding. Really. Add padding to the last block if really want. but... don't. 76 | plaintext = self.padding.remove(from: plaintext, blockSize: self.blockSize - self.lastBlockRemainder) 77 | } 78 | 79 | self.accumulated.removeFirst(processedBytesCount) // super-slow 80 | 81 | if var finalizingWorker = worker as? FinalizingDecryptModeWorker, isLast == true { 82 | plaintext = Array(try finalizingWorker.finalize(decrypt: plaintext.slice)) 83 | } 84 | 85 | return plaintext 86 | } 87 | 88 | @inlinable 89 | public func seek(to position: Int) throws { 90 | guard var worker = self.worker as? SeekableModeWorker else { 91 | throw Error.unsupported 92 | } 93 | 94 | try worker.seek(to: position) 95 | self.worker = worker 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/StreamEncryptor.swift: -------------------------------------------------------------------------------- 1 | // CryptoSwift 2 | // 3 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 4 | // This software is provided 'as-is', without any express or implied warranty. 5 | // 6 | // In no event will the authors be held liable for any damages arising from the use of this software. 7 | // 8 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | // 10 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 11 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | // - This notice may not be removed or altered from any source or binary distribution. 13 | // 14 | 15 | @usableFromInline 16 | final class StreamEncryptor: Cryptor, Updatable { 17 | 18 | @usableFromInline 19 | enum Error: Swift.Error { 20 | case unsupported 21 | } 22 | 23 | @usableFromInline 24 | internal let blockSize: Int 25 | 26 | @usableFromInline 27 | internal var worker: CipherModeWorker 28 | 29 | @usableFromInline 30 | internal let padding: Padding 31 | 32 | @usableFromInline 33 | internal var lastBlockRemainder = 0 34 | 35 | @usableFromInline 36 | init(blockSize: Int, padding: Padding, _ worker: CipherModeWorker) throws { 37 | self.blockSize = blockSize 38 | self.padding = padding 39 | self.worker = worker 40 | } 41 | 42 | // MARK: Updatable 43 | 44 | @inlinable 45 | public func update(withBytes bytes: ArraySlice, isLast: Bool) throws -> Array { 46 | var accumulated = Array(bytes) 47 | if isLast { 48 | // CTR doesn't need padding. Really. Add padding to the last block if really want. but... don't. 49 | accumulated = self.padding.add(to: accumulated, blockSize: self.blockSize - self.lastBlockRemainder) 50 | } 51 | 52 | var encrypted = Array(reserveCapacity: bytes.count) 53 | for chunk in accumulated.batched(by: self.blockSize) { 54 | encrypted += self.worker.encrypt(block: chunk) 55 | } 56 | 57 | // omit unnecessary calculation if not needed 58 | if self.padding != .noPadding { 59 | self.lastBlockRemainder = encrypted.count.quotientAndRemainder(dividingBy: self.blockSize).remainder 60 | } 61 | 62 | if var finalizingWorker = worker as? FinalizingEncryptModeWorker, isLast == true { 63 | encrypted = Array(try finalizingWorker.finalize(encrypt: encrypted.slice)) 64 | } 65 | 66 | return encrypted 67 | } 68 | 69 | @usableFromInline 70 | func seek(to: Int) throws { 71 | throw Error.unsupported 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/String+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | /** String extension */ 19 | extension String { 20 | 21 | @inlinable 22 | public var bytes: Array { 23 | data(using: String.Encoding.utf8, allowLossyConversion: true)?.bytes ?? Array(utf8) 24 | } 25 | 26 | @inlinable 27 | public func md5() -> String { 28 | self.bytes.md5().toHexString() 29 | } 30 | 31 | @inlinable 32 | public func sha1() -> String { 33 | self.bytes.sha1().toHexString() 34 | } 35 | 36 | @inlinable 37 | public func sha224() -> String { 38 | self.bytes.sha224().toHexString() 39 | } 40 | 41 | @inlinable 42 | public func sha256() -> String { 43 | self.bytes.sha256().toHexString() 44 | } 45 | 46 | @inlinable 47 | public func sha384() -> String { 48 | self.bytes.sha384().toHexString() 49 | } 50 | 51 | @inlinable 52 | public func sha512() -> String { 53 | self.bytes.sha512().toHexString() 54 | } 55 | 56 | @inlinable 57 | public func sha3(_ variant: SHA3.Variant) -> String { 58 | self.bytes.sha3(variant).toHexString() 59 | } 60 | 61 | @inlinable 62 | public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> String { 63 | self.bytes.crc32(seed: seed, reflect: reflect).bytes().toHexString() 64 | } 65 | 66 | @inlinable 67 | public func crc32c(seed: UInt32? = nil, reflect: Bool = true) -> String { 68 | self.bytes.crc32c(seed: seed, reflect: reflect).bytes().toHexString() 69 | } 70 | 71 | @inlinable 72 | public func crc16(seed: UInt16? = nil) -> String { 73 | self.bytes.crc16(seed: seed).bytes().toHexString() 74 | } 75 | 76 | /// - parameter cipher: Instance of `Cipher` 77 | /// - returns: hex string of bytes 78 | @inlinable 79 | public func encrypt(cipher: Cipher) throws -> String { 80 | try self.bytes.encrypt(cipher: cipher).toHexString() 81 | } 82 | 83 | /// - parameter cipher: Instance of `Cipher` 84 | /// - returns: base64 encoded string of encrypted bytes 85 | @inlinable 86 | public func encryptToBase64(cipher: Cipher) throws -> String { 87 | try self.bytes.encrypt(cipher: cipher).toBase64() 88 | } 89 | 90 | // decrypt() does not make sense for String 91 | 92 | /// - parameter authenticator: Instance of `Authenticator` 93 | /// - returns: hex string of string 94 | @inlinable 95 | public func authenticate(with authenticator: A) throws -> String { 96 | try self.bytes.authenticate(with: authenticator).toHexString() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/UInt128.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UInt128.swift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | struct UInt128: Equatable, ExpressibleByIntegerLiteral { 19 | let i: (a: UInt64, b: UInt64) 20 | 21 | typealias IntegerLiteralType = UInt64 22 | 23 | init(integerLiteral value: IntegerLiteralType) { 24 | self = UInt128(value) 25 | } 26 | 27 | init(_ raw: Array) { 28 | self = raw.prefix(MemoryLayout.stride).withUnsafeBytes({ (rawBufferPointer) -> UInt128 in 29 | let arr = rawBufferPointer.bindMemory(to: UInt64.self) 30 | return UInt128((arr[0].bigEndian, arr[1].bigEndian)) 31 | }) 32 | } 33 | 34 | init(_ raw: ArraySlice) { 35 | self.init(Array(raw)) 36 | } 37 | 38 | init(_ i: (a: UInt64, b: UInt64)) { 39 | self.i = i 40 | } 41 | 42 | init(a: UInt64, b: UInt64) { 43 | self.init((a, b)) 44 | } 45 | 46 | init(_ b: UInt64) { 47 | self.init((0, b)) 48 | } 49 | 50 | // Bytes 51 | var bytes: Array { 52 | var at = self.i.a.bigEndian 53 | var bt = self.i.b.bigEndian 54 | 55 | let ar = Data(bytes: &at, count: MemoryLayout.size(ofValue: at)) 56 | let br = Data(bytes: &bt, count: MemoryLayout.size(ofValue: bt)) 57 | 58 | var result = Data() 59 | result.append(ar) 60 | result.append(br) 61 | return result.bytes 62 | } 63 | 64 | static func ^ (n1: UInt128, n2: UInt128) -> UInt128 { 65 | UInt128((n1.i.a ^ n2.i.a, n1.i.b ^ n2.i.b)) 66 | } 67 | 68 | static func & (n1: UInt128, n2: UInt128) -> UInt128 { 69 | UInt128((n1.i.a & n2.i.a, n1.i.b & n2.i.b)) 70 | } 71 | 72 | static func >> (value: UInt128, by: Int) -> UInt128 { 73 | var result = value 74 | for _ in 0..> 1 76 | let b = result.i.b >> 1 + ((result.i.a & 1) << 63) 77 | result = UInt128((a, b)) 78 | } 79 | return result 80 | } 81 | 82 | // Equatable. 83 | static func == (lhs: UInt128, rhs: UInt128) -> Bool { 84 | lhs.i == rhs.i 85 | } 86 | 87 | static func != (lhs: UInt128, rhs: UInt128) -> Bool { 88 | !(lhs == rhs) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/UInt16+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /** array of bytes */ 17 | extension UInt16 { 18 | @_specialize(where T == ArraySlice) 19 | init(bytes: T) where T.Element == UInt8, T.Index == Int { 20 | self = UInt16(bytes: bytes, fromIndex: bytes.startIndex) 21 | } 22 | 23 | @_specialize(where T == ArraySlice) 24 | init(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int { 25 | if bytes.isEmpty { 26 | self = 0 27 | return 28 | } 29 | 30 | let count = bytes.count 31 | 32 | let val0 = count > 0 ? UInt16(bytes[index.advanced(by: 0)]) << 8 : 0 33 | let val1 = count > 1 ? UInt16(bytes[index.advanced(by: 1)]) : 0 34 | 35 | self = val0 | val1 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/UInt32+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #if canImport(Darwin) 17 | import Darwin 18 | #elseif canImport(Android) 19 | import Android 20 | #elseif canImport(Glibc) 21 | import Glibc 22 | #elseif canImport(Musl) 23 | import Musl 24 | #elseif canImport(ucrt) 25 | import ucrt 26 | #endif 27 | 28 | protocol _UInt32Type {} 29 | extension UInt32: _UInt32Type {} 30 | 31 | /** array of bytes */ 32 | extension UInt32 { 33 | @_specialize(where T == ArraySlice) 34 | init(bytes: T) where T.Element == UInt8, T.Index == Int { 35 | self = UInt32(bytes: bytes, fromIndex: bytes.startIndex) 36 | } 37 | 38 | @_specialize(where T == ArraySlice) 39 | @inlinable 40 | init(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int { 41 | if bytes.isEmpty { 42 | self = 0 43 | return 44 | } 45 | 46 | let count = bytes.count 47 | 48 | let val0 = count > 0 ? UInt32(bytes[index.advanced(by: 0)]) << 24 : 0 49 | let val1 = count > 1 ? UInt32(bytes[index.advanced(by: 1)]) << 16 : 0 50 | let val2 = count > 2 ? UInt32(bytes[index.advanced(by: 2)]) << 8 : 0 51 | let val3 = count > 3 ? UInt32(bytes[index.advanced(by: 3)]) : 0 52 | 53 | self = val0 | val1 | val2 | val3 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/UInt64+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /** array of bytes */ 17 | extension UInt64 { 18 | @_specialize(where T == ArraySlice) 19 | init(bytes: T) where T.Element == UInt8, T.Index == Int { 20 | self = UInt64(bytes: bytes, fromIndex: bytes.startIndex) 21 | } 22 | 23 | @_specialize(where T == ArraySlice) 24 | @inlinable 25 | init(bytes: T, fromIndex index: T.Index) where T.Element == UInt8, T.Index == Int { 26 | if bytes.isEmpty { 27 | self = 0 28 | return 29 | } 30 | 31 | let count = bytes.count 32 | 33 | let val0 = count > 0 ? UInt64(bytes[index.advanced(by: 0)]) << 56 : 0 34 | let val1 = count > 1 ? UInt64(bytes[index.advanced(by: 1)]) << 48 : 0 35 | let val2 = count > 2 ? UInt64(bytes[index.advanced(by: 2)]) << 40 : 0 36 | let val3 = count > 3 ? UInt64(bytes[index.advanced(by: 3)]) << 32 : 0 37 | let val4 = count > 4 ? UInt64(bytes[index.advanced(by: 4)]) << 24 : 0 38 | let val5 = count > 5 ? UInt64(bytes[index.advanced(by: 5)]) << 16 : 0 39 | let val6 = count > 6 ? UInt64(bytes[index.advanced(by: 6)]) << 8 : 0 40 | let val7 = count > 7 ? UInt64(bytes[index.advanced(by: 7)]) : 0 41 | 42 | self = val0 | val1 | val2 | val3 | val4 | val5 | val6 | val7 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/UInt8+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #if canImport(Darwin) 17 | import Darwin 18 | #elseif canImport(Android) 19 | import Android 20 | #elseif canImport(Glibc) 21 | import Glibc 22 | #elseif canImport(Musl) 23 | import Musl 24 | #elseif canImport(ucrt) 25 | import ucrt 26 | #endif 27 | 28 | public protocol _UInt8Type {} 29 | extension UInt8: _UInt8Type {} 30 | 31 | /** casting */ 32 | extension UInt8 { 33 | /** cast because UInt8() because std initializer crash if value is > byte */ 34 | static func with(value: UInt64) -> UInt8 { 35 | let tmp = value & 0xff 36 | return UInt8(tmp) 37 | } 38 | 39 | static func with(value: UInt32) -> UInt8 { 40 | let tmp = value & 0xff 41 | return UInt8(tmp) 42 | } 43 | 44 | static func with(value: UInt16) -> UInt8 { 45 | let tmp = value & 0xff 46 | return UInt8(tmp) 47 | } 48 | } 49 | 50 | /** Bits */ 51 | extension UInt8 { 52 | /** array of bits */ 53 | public func bits() -> [Bit] { 54 | let totalBitsCount = MemoryLayout.size * 8 55 | 56 | var bitsArray = [Bit](repeating: Bit.zero, count: totalBitsCount) 57 | 58 | for j in 0.. String { 70 | var s = String() 71 | let arr: [Bit] = self.bits() 72 | for idx in arr.indices { 73 | s += (arr[idx] == Bit.one ? "1" : "0") 74 | if idx.advanced(by: 1) % 8 == 0 { s += " " } 75 | } 76 | return s 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Sources/CryptoSwift/ZeroPadding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | /// All the bytes that are required to be padded are padded with zero. 17 | /// Zero padding may not be reversible if the original file ends with one or more zero bytes. 18 | struct ZeroPadding: PaddingProtocol { 19 | init() { 20 | } 21 | 22 | @inlinable 23 | func add(to bytes: Array, blockSize: Int) -> Array { 24 | let paddingCount = blockSize - (bytes.count % blockSize) 25 | if paddingCount > 0 { 26 | return bytes + Array(repeating: 0, count: paddingCount) 27 | } 28 | return bytes 29 | } 30 | 31 | @inlinable 32 | func remove(from bytes: Array, blockSize _: Int?) -> Array { 33 | for (idx, value) in bytes.reversed().enumerated() { 34 | if value != 0 { 35 | return Array(bytes[0.. 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | import XCTest 18 | @testable import CryptoSwift 19 | 20 | final class AESTestsPerf: XCTestCase { 21 | func testAESEncryptPerformance() { 22 | let key: Array = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c] 23 | let iv: Array = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 24 | let message = Array(repeating: 7, count: 1024 * 1024) 25 | let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7) 26 | measure { 27 | _ = try! aes.encrypt(message) 28 | } 29 | } 30 | 31 | func testAESDecryptPerformance() { 32 | let key: Array = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c] 33 | let iv: Array = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] 34 | let message = Array(repeating: 7, count: 1024 * 1024) 35 | let aes = try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7) 36 | measure { 37 | _ = try! aes.decrypt(message) 38 | } 39 | } 40 | } 41 | 42 | extension AESTestsPerf { 43 | static func allTests() -> [(String, (AESTestsPerf) -> () -> Void)] { 44 | let tests = [ 45 | ("testAESEncryptPerformance", testAESEncryptPerformance), 46 | ("testAESDecryptPerformance", testAESDecryptPerformance) 47 | ] 48 | return tests 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/Bridging.h: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | #ifndef CryptoSwift_Bridging_h 17 | #define CryptoSwift_Bridging_h 18 | 19 | #import 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/ChaCha20TestsPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | import XCTest 18 | @testable import CryptoSwift 19 | 20 | final class ChaCha20TestsPerf: XCTestCase { 21 | func testChaCha20Performance() { 22 | let key: Array = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f] 23 | let iv: Array = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07] 24 | let message = Array(repeating: 7, count: 1024 * 1024) 25 | measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true) { () -> Void in 26 | do { 27 | _ = try ChaCha20(key: key, iv: iv).encrypt(message) 28 | } catch { 29 | XCTFail() 30 | } 31 | self.stopMeasuring() 32 | } 33 | } 34 | } 35 | 36 | extension ChaCha20TestsPerf { 37 | static func allTests() -> [(String, (ChaCha20TestsPerf) -> () -> Void)] { 38 | let tests = [("testChaCha20Performance", testChaCha20Performance)] 39 | return tests 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/DigestTestsPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | // http://www.di-mgt.com.au/sha_testvectors.html (http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf) 17 | // 18 | 19 | import Foundation 20 | import XCTest 21 | @testable import CryptoSwift 22 | 23 | final class DigestTestsPerf: XCTestCase { 24 | func testMD5Performance() { 25 | measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: false) { 26 | let arr = Array(repeating: 200, count: 1024 * 1024) 27 | self.startMeasuring() 28 | _ = Digest.md5(arr) 29 | self.stopMeasuring() 30 | } 31 | } 32 | 33 | func testSHA1Performance() { 34 | measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: false) { 35 | let arr = Array(repeating: 200, count: 1024 * 1024) 36 | self.startMeasuring() 37 | _ = Digest.sha1(arr) 38 | self.stopMeasuring() 39 | } 40 | } 41 | 42 | // Keep it to compare 43 | /* 44 | func testSHA1PerformanceCC() { 45 | measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: false) { 46 | let arr = Array(repeating: 200, count: 1024 * 1024) 47 | self.startMeasuring() 48 | var digest = Array(repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) 49 | CC_SHA1(arr, CC_LONG(arr.count), &digest) 50 | self.stopMeasuring() 51 | } 52 | } 53 | */ 54 | } 55 | 56 | extension DigestTestsPerf { 57 | static func allTests() -> [(String, (DigestTestsPerf) -> () -> Void)] { 58 | [ 59 | ("testMD5Performance", testMD5Performance), 60 | ("testSHA1Performance", testSHA1Performance) 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/Error+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | 18 | #if !_runtime(_ObjC) 19 | 20 | extension Error { 21 | var localizedDescription: String { 22 | "\(self)" 23 | } 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/ExtensionsTestPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | import XCTest 18 | @testable import CryptoSwift 19 | 20 | final class ExtensionsTestPerf: XCTestCase { 21 | func testArrayInitHexPerformance() { 22 | var str = "b1b2b3b3b3b3b3b3b1b2b3b3b3b3b3b3" 23 | for _ in 0...12 { 24 | str += str 25 | } 26 | measure { 27 | _ = Array(hex: str) 28 | } 29 | } 30 | } 31 | 32 | extension ExtensionsTestPerf { 33 | static func allTests() -> [(String, (ExtensionsTestPerf) -> () -> Void)] { 34 | let tests = [ 35 | ("testArrayInitHexPerformance", testArrayInitHexPerformance) 36 | ] 37 | return tests 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/PBKDFPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import XCTest 17 | @testable import CryptoSwift 18 | 19 | class PBKDFPerf: XCTestCase { 20 | func testPerformance() { 21 | let password: Array = "s33krit".bytes 22 | let salt: Array = "nacl".bytes 23 | measure { 24 | _ = try! PKCS5.PBKDF2(password: password, salt: salt, iterations: 65536, keyLength: 32, variant: .sha1).calculate() 25 | } 26 | } 27 | 28 | static func allTests() -> [(String, (PBKDFPerf) -> () -> Void)] { 29 | let tests = [("testPerformance", testPerformance)] 30 | return tests 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/RabbitTestsPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import XCTest 17 | @testable import CryptoSwift 18 | 19 | class RabbitTestsPerf: XCTestCase { 20 | func testRabbitPerformance() { 21 | let key: Array = Array(repeating: 0, count: Rabbit.keySize) 22 | let iv: Array = Array(repeating: 0, count: Rabbit.ivSize) 23 | let message = Array(repeating: 7, count: (1024 * 1024) * 1) 24 | measure { 25 | _ = try! Rabbit(key: key, iv: iv).encrypt(message) 26 | } 27 | } 28 | } 29 | 30 | extension RabbitTestsPerf { 31 | static func allTests() -> [(String, (RabbitTestsPerf) -> () -> Void)] { 32 | let tests = [ 33 | ("testRabbitPerformance", testRabbitPerformance) 34 | ] 35 | return tests 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/SHATestsPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2017 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import Foundation 17 | import XCTest 18 | @testable import CryptoSwift 19 | 20 | final class SHATestsPerf: XCTestCase { 21 | 22 | static let len = 100000 23 | let a = [UInt8](unsafeUninitializedCapacity: SHATestsPerf.len) { buf, count in 24 | for i in 0.. 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import XCTest 17 | @testable import CryptoSwift 18 | 19 | class Scrypt: XCTestCase { 20 | 21 | func testScrypt_0() { 22 | let password = Array("password".data(using: .ascii)!) 23 | let salt = Array("NaCl".data(using: .ascii)!) 24 | let deriver = try! CryptoSwift.Scrypt(password: password, salt: salt, dkLen: 64, N: 1024, r: 8, p: 16) 25 | let derived = try! deriver.calculate() 26 | let expected: [UInt8] = Array.init(hex: """ 27 | fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 28 | 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 29 | 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da 30 | c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 31 | """.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "")) 32 | XCTAssertEqual(derived, expected) 33 | } 34 | 35 | func testScrypt_1() { 36 | let password = Array("pleaseletmein".data(using: .ascii)!) 37 | let salt = Array("SodiumChloride".data(using: .ascii)!) 38 | let deriver = try! CryptoSwift.Scrypt(password: password, salt: salt, dkLen: 64, N: 16384, r: 8, p: 1) 39 | let derived = try! deriver.calculate() 40 | let expected: [UInt8] = Array.init(hex: """ 41 | 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb 42 | fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 43 | d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 44 | e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 45 | """.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "")) 46 | XCTAssertEqual(derived, expected) 47 | } 48 | 49 | // Takes too long to run in debug mode! 50 | func testScrypt_2() { 51 | #if !DEBUG 52 | let password = Array("pleaseletmein".data(using: .ascii)!) 53 | let salt = Array("SodiumChloride".data(using: .ascii)!) 54 | let deriver = try! CryptoSwift.Scrypt(password: password, salt: salt, dkLen: 64, N: 1048576, r: 8, p: 1) 55 | let derived = try! deriver.calculate() 56 | let expected: [UInt8] = Array.init(hex: """ 57 | 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 58 | ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 59 | 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 60 | 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 61 | """.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "")) 62 | XCTAssertEqual(derived, expected) 63 | #endif 64 | } 65 | 66 | static let allTests = [ 67 | ("testScrypt_0", testScrypt_0), 68 | ("testScrypt_1", testScrypt_1), 69 | ("testScrypt_2", testScrypt_2) 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/ScryptTestsPerf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) 2014-2025 Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import XCTest 17 | @testable import CryptoSwift 18 | 19 | class ScryptTestsPeft: XCTestCase { 20 | func testScryptPerformance() { 21 | let N = 16384 22 | let password: Array = Array(repeating: 0, count: 32) 23 | let salt: Array = Array(repeating: 0, count: 32) 24 | measure { 25 | _ = try! CryptoSwift.Scrypt(password: password, salt: salt, dkLen: 64, N: N, r: 8, p: 1).calculate() 26 | } 27 | } 28 | } 29 | 30 | extension ScryptTestsPeft { 31 | static func allTests() -> [(String, (ScryptTestsPeft) -> () -> Void)] { 32 | let tests = [ 33 | ("testScryptPerformance", testScryptPerformance) 34 | ] 35 | return tests 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Tests/CryptoSwiftTests/XChaCha20Poly1305Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift 3 | // 4 | // Copyright (C) Marcin Krzyżanowski 5 | // This software is provided 'as-is', without any express or implied warranty. 6 | // 7 | // In no event will the authors be held liable for any damages arising from the use of this software. 8 | // 9 | // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | // 11 | // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. 12 | // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | // - This notice may not be removed or altered from any source or binary distribution. 14 | // 15 | 16 | import XCTest 17 | @testable import CryptoSwift 18 | 19 | class XChaCha20Poly1305Tests: XCTestCase { 20 | 21 | /// See: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.3.1 22 | func testRoundTrip() { 23 | do { 24 | let plaintext: Array = .init( 25 | hex: """ 26 | 4c616469657320616e642047656e746c656d656e206f662074686520636c6173 27 | 73206f66202739393a204966204920636f756c64206f6666657220796f75206f 28 | 6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73 29 | 637265656e20776f756c642062652069742e 30 | """.replacingOccurrences(of: "\n", with: "") 31 | ) 32 | let aad: Array = .init( 33 | hex: "50515253c0c1c2c3c4c5c6c7") 34 | let key: Array = .init( 35 | hex: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") 36 | let iv: Array = .init( 37 | hex: "404142434445464748494a4b4c4d4e4f5051525354555657") 38 | 39 | let encryptResult = try AEADXChaCha20Poly1305.encrypt( 40 | plaintext, 41 | key: key, 42 | iv: iv, 43 | authenticationHeader: aad 44 | ) 45 | 46 | XCTAssertEqual( 47 | encryptResult.cipherText.toHexString(), 48 | """ 49 | bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb 50 | 731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b452 51 | 2f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff9 52 | 21f9664c97637da9768812f615c68b13b52e 53 | """.replacingOccurrences(of: "\n", with: "") 54 | ) 55 | 56 | XCTAssertEqual( 57 | encryptResult.authenticationTag.toHexString(), 58 | "c0875924c1c7987947deafd8780acf49" 59 | ) 60 | 61 | let decryptResult = try AEADXChaCha20Poly1305.decrypt( 62 | encryptResult.cipherText, 63 | key: key, 64 | iv: iv, 65 | authenticationHeader: aad, 66 | authenticationTag: encryptResult.authenticationTag 67 | ) 68 | 69 | XCTAssertEqual(decryptResult.plainText, plaintext) 70 | } catch { 71 | XCTFail(error.localizedDescription) 72 | } 73 | } 74 | 75 | static let allTests = [ 76 | ("Test Vector for AEAD_XCHACHA20_POLY1305", testRoundTrip) 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import CryptoSwiftTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += CryptoSwiftTests.__allTests() 7 | 8 | XCTMain(tests) 9 | -------------------------------------------------------------------------------- /Tests/TestsPerformance/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | #if !canImport(ObjectiveC) 2 | import XCTest 3 | 4 | extension TestsPerformance { 5 | // DO NOT MODIFY: This is autogenerated, use: 6 | // `swift test --generate-linuxmain` 7 | // to regenerate. 8 | static let __allTests__TestsPerformance = [ 9 | ("testExample", testExample), 10 | ("testPerformanceExample", testPerformanceExample), 11 | ] 12 | } 13 | 14 | public func __allTests() -> [XCTestCaseEntry] { 15 | return [ 16 | testCase(TestsPerformance.__allTests__TestsPerformance), 17 | ] 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal 2 | -------------------------------------------------------------------------------- /config/CryptoSwift-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "CryptoSwift-Shared.xcconfig" 2 | 3 | OTHER_SWIFT_FLAGS = $(inherited) -Xfrontend -debug-time-function-bodies 4 | SWIFT_COMPILATION_MODE = incremental 5 | SWIFT_OPTIMIZATION_LEVEL = -Onone 6 | SWIFT_ENFORCE_EXCLUSIVE_ACCESS = none 7 | -------------------------------------------------------------------------------- /config/CryptoSwift-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "CryptoSwift-Shared.xcconfig" 2 | 3 | BITCODE_GENERATION_MODE = bitcode 4 | CLANG_USE_OPTIMIZATION_PROFILE = NO 5 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO 6 | GCC_UNROLL_LOOPS = YES 7 | LLVM_LTO = YES 8 | SWIFT_DISABLE_SAFETY_CHECKS = YES 9 | SWIFT_ENFORCE_EXCLUSIVE_ACCESS = compile-time 10 | SWIFT_OPTIMIZATION_LEVEL = -O 11 | -------------------------------------------------------------------------------- /config/CryptoSwift-Shared.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES 2 | APPLICATION_EXTENSION_API_ONLY = YES 3 | DYLIB_COMPATIBILITY_VERSION = 1 4 | DYLIB_CURRENT_VERSION = 1 5 | DYLIB_INSTALL_NAME_BASE = @rpath 6 | 7 | ENABLE_BITCODE = NO 8 | ENABLE_BITCODE[sdk=macosx*] = NO 9 | 10 | INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks 11 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 12 | INFOPLIST_FILE = Info.plist 13 | PRODUCT_BUNDLE_IDENTIFIER = com.krzyzanowskim.${PRODUCT_NAME:rfc1034identifier} 14 | PRODUCT_NAME = $(TARGET_NAME) 15 | SKIP_INSTALL = YES 16 | DEAD_CODE_STRIPPING = YES 17 | -------------------------------------------------------------------------------- /config/CryptoSwift-Test.xcconfig: -------------------------------------------------------------------------------- 1 | #include "CryptoSwift-Shared.xcconfig" 2 | 3 | ENABLE_TESTABILITY = YES 4 | STRIP_INSTALLED_PRODUCT = NO 5 | 6 | // Disable for tests. https://twitter.com/krzyzanowskim/status/1191515868401983489 7 | BUILD_LIBRARY_FOR_DISTRIBUTION = NO 8 | COPY_PHASE_STRIP = NO 9 | -------------------------------------------------------------------------------- /config/CryptoSwift-TestHostApp-Shared.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift-TestHostApp-Shared.xcconfig 3 | // 4 | // Generated by BuildSettingExtractor on 02/04/2018 5 | // https://github.com/dempseyatgithub/BuildSettingExtractor 6 | // 7 | 8 | CODE_SIGN_STYLE = Automatic 9 | CODE_SIGN_IDENTITY = iPhone Developer 10 | DEVELOPMENT_TEAM = HA4H7JURM8 11 | PROVISIONING_PROFILE_SPECIFIER = 12 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 13 | 14 | // Asset Catalog App Icon Set Name 15 | // 16 | // Name of an asset catalog app icon set whose contents will be merged into the 17 | // `Info.plist`. 18 | 19 | ASSETCATALOG_COMPILER_APPICON_NAME = 20 | 21 | 22 | // Info.plist File 23 | // 24 | // The project-relative path to the property list file that contains the `Info.plist` 25 | // information used by bundles. For details on information property list files, see 26 | // [Information Property List 27 | // Files](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigFiles.html#//apple_ref/doc/uid/20002091-CJBJIEDH) 28 | // in [Runtime Configuration 29 | // Guidelines](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPRuntimeConfig/000-Introduction/introduction.html). 30 | 31 | INFOPLIST_FILE = CryptoSwift-TestHostApp/Info.plist 32 | 33 | 34 | 35 | // Runpath Search Paths 36 | // 37 | // This is a list of paths to be added to the `runpath` search path list for the image 38 | // being created. At runtime, `dyld` uses the `runpath` when searching for dylibs whose 39 | // load path begins with `@rpath/`. See [Dynamic Library Programming 40 | // Topics](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html). 41 | 42 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks 43 | 44 | 45 | 46 | // Product Bundle Identifier 47 | // 48 | // A string that uniquely identifies the bundle. The string should be in reverse DNS 49 | // format using only alphanumeric characters (`A-Z`, `a-z`, `0-9`), the dot (`.`), and 50 | // the hyphen (`-`). This value is used as the `CFBundleIdentifier` in the `Info.plist` 51 | // of the built bundle. 52 | 53 | PRODUCT_BUNDLE_IDENTIFIER = test.CryptoSwiftTestHostApp 54 | 55 | 56 | // Base SDK 57 | // 58 | // The name or path of the base SDK being used during the build. The product will be 59 | // built against the headers and libraries located inside the indicated SDK. This path 60 | // will be prepended to all search paths, and will be passed through the environment to 61 | // the compiler and linker. Additional SDKs can be specified in the `ADDITIONAL_SDKS` 62 | // setting. 63 | 64 | SDKROOT = iphoneos 65 | SUPPORTED_PLATFORMS = iphonesimulator iphoneos 66 | 67 | COPY_PHASE_STRIP = NO 68 | ONLY_ACTIVE_ARCH = YES 69 | -------------------------------------------------------------------------------- /config/CryptoSwift-TestHostApp-Test.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoSwift-TestHostApp-Test.xcconfig 3 | // 4 | // Generated by BuildSettingExtractor on 02/04/2018 5 | // https://github.com/dempseyatgithub/BuildSettingExtractor 6 | // 7 | 8 | #include "CryptoSwift-TestHostApp-Shared.xcconfig" 9 | 10 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym 11 | ENABLE_NS_ASSERTIONS = NO 12 | MTL_ENABLE_DEBUG_INFO = NO 13 | SWIFT_OPTIMIZATION_LEVEL = -O 14 | VALIDATE_PRODUCT = YES 15 | -------------------------------------------------------------------------------- /config/Project-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Project-Shared.xcconfig" 2 | 3 | COPY_PHASE_STRIP = NO 4 | GCC_DYNAMIC_NO_PIC = NO 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1 6 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG 7 | METAL_ENABLE_DEBUG_INFO = YES 8 | ONLY_ACTIVE_ARCH = YES 9 | ENABLE_TESTABILITY = YES 10 | -------------------------------------------------------------------------------- /config/Project-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Project-Shared.xcconfig" 2 | 3 | CODE_SIGN_IDENTITY[sdk=macosx*] = Developer ID Application 4 | 5 | CLANG_USE_OPTIMIZATION_PROFILE = YES 6 | COPY_PHASE_STRIP = YES 7 | ENABLE_NS_ASSERTIONS = NO 8 | GCC_OPTIMIZATION_LEVEL = fast 9 | METAL_ENABLE_DEBUG_INFO = NO 10 | VALIDATE_PRODUCT = YES 11 | -------------------------------------------------------------------------------- /config/Project-Shared.xcconfig: -------------------------------------------------------------------------------- 1 | MARKETING_VERSION = 1.8.4 2 | 3 | SUPPORTED_PLATFORMS = iphonesimulator iphoneos macosx appletvos watchos appletvsimulator watchsimulator xrsimulator xros 4 | 5 | SWIFT_COMPILATION_MODE = wholemodule 6 | SWIFT_VERSION = 5.0 7 | 8 | TARGETED_DEVICE_FAMILY = 1,2,3,4 9 | 10 | TVOS_DEPLOYMENT_TARGET = 11.0 11 | IPHONEOS_DEPLOYMENT_TARGET = 11.0 12 | MACOSX_DEPLOYMENT_TARGET = 10.13 13 | WATCHOS_DEPLOYMENT_TARGET = 4.0 14 | XROS_DEPLOYMENT_TARGET = 1.0 15 | 16 | DEVELOPMENT_TEAM = 17 | //PROVISIONING_PROFILE = 18 | //PROVISIONING_PROFILE_SPECIFIER = 19 | 20 | CODE_SIGN_IDENTITY[sdk=macosx*] = Mac Developer 21 | CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer 22 | CODE_SIGN_IDENTITY[sdk=iphonesimulator*] = iPhone Developer 23 | CODE_SIGN_STYLE = Automatic 24 | 25 | PRODUCT_NAME = ${TARGET_NAME} 26 | 27 | CLANG_ANALYZER_NONNULL = YES 28 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE 29 | 30 | ALWAYS_SEARCH_USER_PATHS = NO 31 | 32 | CLANG_CXX_LANGUAGE_STANDARD = gnu++0x 33 | CLANG_CXX_LIBRARY = libc++ 34 | CLANG_ENABLE_MODULES = YES 35 | CLANG_ENABLE_OBJC_ARC = YES 36 | CLANG_ENABLE_OBJC_WEAK = YES 37 | 38 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 39 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES 40 | CLANG_WARN_BOOL_CONVERSION = YES 41 | CLANG_WARN_COMMA = YES 42 | CLANG_WARN_CONSTANT_CONVERSION = YES 43 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 44 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR 45 | CLANG_WARN_EMPTY_BODY = YES 46 | CLANG_WARN_ENUM_CONVERSION = YES 47 | CLANG_WARN_INFINITE_RECURSION = YES 48 | CLANG_WARN_INT_CONVERSION = YES 49 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES 50 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 51 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES 52 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR 53 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES 54 | CLANG_WARN_STRICT_PROTOTYPES = YES 55 | CLANG_WARN_SUSPICIOUS_MOVE = YES 56 | CLANG_WARN_UNREACHABLE_CODE = YES 57 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES 58 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 59 | 60 | DEBUG_INFORMATION_FORMAT = dwarf 61 | DEFINES_MODULE = YES 62 | 63 | ENABLE_STRICT_OBJC_MSGSEND = YES 64 | 65 | GCC_C_LANGUAGE_STANDARD = gnu99 66 | GCC_NO_COMMON_BLOCKS = YES 67 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 68 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR 69 | GCC_WARN_UNDECLARED_SELECTOR = YES 70 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE 71 | GCC_WARN_UNUSED_FUNCTION = YES 72 | GCC_WARN_UNUSED_LABEL = YES 73 | GCC_WARN_UNUSED_VARIABLE = YES 74 | 75 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES 76 | 77 | VERSION_INFO_PREFIX = 78 | VERSIONING_SYSTEM = apple-generic 79 | CURRENT_PROJECT_VERSION = 1 80 | 81 | // XCFramework 82 | // Swift have (at least) 2 language dialects: With and without Library Evolution behave differently regarding enums. 83 | BUILD_LIBRARY_FOR_DISTRIBUTION = YES 84 | 85 | // Catalyst 86 | SUPPORTS_MACCATALYST = YES 87 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES 88 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO 89 | -------------------------------------------------------------------------------- /config/Tests-Shared.xcconfig: -------------------------------------------------------------------------------- 1 | DEVELOPMENT_TEAM = 2 | CODE_SIGN_IDENTITY = 3 | CODE_SIGN_STYLE = Manual 4 | CODE_SIGNING_REQUIRED = NO 5 | 6 | HEADER_SEARCH_PATHS = $(inherited) includes/** 7 | 8 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks @loader_path/../Frameworks @executable_path/../Frameworks 9 | 10 | PRODUCT_BUNDLE_IDENTIFIER = com.krzyzanowskim.${PRODUCT_NAME:rfc1034identifier} 11 | 12 | OTHER_SWIFT_FLAGS = $(inherited) -Xfrontend -debug-time-function-bodies 13 | 14 | // Disable for tests. https://twitter.com/krzyzanowskim/status/1191515868401983489 15 | BUILD_LIBRARY_FOR_DISTRIBUTION = NO 16 | 17 | MACOSX_DEPLOYMENT_TARGET = 10.15 18 | 19 | INFOPLIST_FILE = Info.plist 20 | -------------------------------------------------------------------------------- /config/Tests-Test.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Tests-Shared.xcconfig" 2 | 3 | COPY_PHASE_STRIP = NO 4 | ENABLE_NS_ASSERTIONS = NO 5 | ENABLE_TESTABILITY = YES 6 | GCC_OPTIMIZATION_LEVEL = fast 7 | 8 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG=1 CI=1 9 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG 10 | 11 | SWIFT_DISABLE_SAFETY_CHECKS = YES 12 | SWIFT_OPTIMIZATION_LEVEL = -O 13 | 14 | METAL_ENABLE_DEBUG_INFO = NO 15 | ONLY_ACTIVE_ARCH = YES 16 | VALIDATE_PRODUCT = YES 17 | -------------------------------------------------------------------------------- /scripts/generate-contributors-list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##===----------------------------------------------------------------------===## 3 | ## 4 | ## This source file is part of the SwiftNIO open source project 5 | ## 6 | ## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors 7 | ## Licensed under Apache License v2.0 8 | ## 9 | ## See LICENSE.txt for license information 10 | ## See CONTRIBUTORS.txt for the list of SwiftNIO project authors 11 | ## 12 | ## SPDX-License-Identifier: Apache-2.0 13 | ## 14 | ##===----------------------------------------------------------------------===## 15 | 16 | set -eu 17 | here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 18 | contributors=$( cd "$here"/.. && git shortlog -es | cut -f2 | sed 's/^/- /' ) 19 | 20 | cat > "$here/../CONTRIBUTORS.txt" <<- EOF 21 | For the purpose of tracking copyright, this is the list of individuals and 22 | organizations who have contributed source code to CryptoSwift. 23 | 24 | ### Contributors 25 | 26 | $contributors 27 | 28 | **Updating this list** 29 | 30 | Please do not edit this file manually. It is generated using \`./scripts/generate-contributors-list.sh\`. If a name is misspelled or appearing multiple times: add an entry in \`./.mailmap\` 31 | EOF 32 | -------------------------------------------------------------------------------- /scripts/swiftformat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | swiftformat --hexliteralcase lowercase --hexgrouping none --ranges nospace --wrapelements beforefirst --self remove $1 4 | --------------------------------------------------------------------------------