├── .gitignore ├── .swiftlint.yml ├── Example ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── TokenCore.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── Pods-TokenCore_Example │ │ ├── Pods-TokenCore_Example-acknowledgements.markdown │ │ ├── Pods-TokenCore_Example-acknowledgements.plist │ │ ├── Pods-TokenCore_Example-frameworks.sh │ │ ├── Pods-TokenCore_Example.debug.xcconfig │ │ └── Pods-TokenCore_Example.release.xcconfig │ │ └── TokenCore │ │ └── TokenCore.xcconfig ├── TokenCore.xcodeproj │ └── project.pbxproj ├── TokenCore.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── TokenCore │ ├── AppDelegate.swift │ ├── AppState.swift │ ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard │ ├── Constants.swift │ ├── FuncListController.swift │ ├── IdentityViewController.swift │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── AppIcon.png │ │ └── Contents.json │ ├── Contents.json │ └── info.imageset │ │ ├── Contents.json │ │ └── info.png │ ├── Info.plist │ ├── LayoutViewController.swift │ ├── NetworkUtil.swift │ ├── ResultController.swift │ ├── Utils.swift │ └── WalletViewController.swift ├── LICENSE ├── Modules └── module.modulemap ├── Podfile ├── Podfile.lock ├── README.md ├── Sources ├── Encryptor │ ├── AES128.swift │ ├── Encryptor.swift │ ├── Hash.swift │ ├── Keccak256.swift │ ├── PBKDF2.swift │ ├── Scrypt.swift │ └── Secp256k1.swift ├── Foundation │ ├── AppError.swift │ ├── BIP44.swift │ ├── Bitcoin │ │ ├── BTCKey.swift │ │ ├── BTCTransaction.swift │ │ ├── BTCTransactionSigner.swift │ │ └── SegWit.swift │ ├── ChainType.swift │ ├── EOS │ │ ├── EOSKey.swift │ │ ├── EOSSignResult.swift │ │ ├── EOSTransaction.swift │ │ └── EOSTransactionSigner.swift │ ├── Ethereum │ │ ├── ETHKey.swift │ │ └── ETHTransaction.swift │ ├── KeyPair.swift │ ├── Mnemonic.swift │ ├── MnemonicDictionary.swift │ ├── MnemonicUtil.swift │ ├── Network.swift │ └── TransactionSignedResult.swift ├── Info.plist ├── Keystore │ ├── Bitcoin │ │ ├── BTCKeystore.swift │ │ └── BTCMnemonicKeystore.swift │ ├── Crypto.swift │ ├── EOS │ │ ├── EOSKeystore.swift │ │ ├── EOSLegacyKeystore.swift │ │ └── EOSPermission.swift │ ├── EncryptedMessage.swift │ ├── Ethereum │ │ ├── ETHKeystore.swift │ │ └── ETHMnemonicKeystore.swift │ ├── Identity │ │ └── IdentityKeystore.swift │ ├── JSONObject.swift │ ├── Keystore.swift │ ├── RandomIV.swift │ └── WalletMeta.swift ├── Storage │ ├── InMemoryStorage.swift │ ├── LocalFileStorage.swift │ ├── Storage.swift │ └── StorageManager.swift ├── TokenCore.h ├── Utils │ ├── BigNumber.swift │ ├── Data+Extension.swift │ ├── Hex.swift │ ├── RLP.swift │ ├── SigUtil.swift │ └── String+Extension.swift ├── Validator │ ├── AddressValidator.swift │ ├── EOSAccountNameValidator.swift │ ├── IdentityValidator.swift │ ├── MnemonicValidator.swift │ ├── PasswordValidator.swift │ ├── PrivateKeyValidator.swift │ ├── V3KeystoreValidator.swift │ ├── Validator.swift │ └── WalletIDValidator.swift └── Wallet │ ├── BasicWallet.swift │ ├── Identity+IPFS.swift │ ├── Identity.swift │ ├── WalletManager+EOS.swift │ └── WalletManager.swift ├── Tests ├── Encryptor │ ├── AES128Tests.swift │ ├── HashTests.swift │ ├── Keccak256Tests.swift │ ├── PBKDF2Tests.swift │ ├── ScryptTests.swift │ └── Secp256k1Tests.swift ├── Fixtures │ ├── EOSMigrationOldAlgorithm.json │ ├── EOSSignTestcase.txt │ ├── exportprivatekeyTest.json │ ├── hd-testpassword.json │ ├── hd-wrong-path-123123.json │ ├── invalid_keystores │ │ ├── address_empty.json │ │ ├── address_wrong.json │ │ ├── cipher_empty.json │ │ ├── cipher_wrong.json │ │ ├── cipherparams_empty.json │ │ ├── cipherparams_wrong.json │ │ ├── ciphertext_empty.json │ │ ├── ciphertext_wrong.json │ │ ├── kdf_empty.json │ │ ├── kdf_wrong.json │ │ ├── kdfparams_dklen_empty.json │ │ ├── kdfparams_empty.json │ │ ├── kdfparams_n_empty.json │ │ ├── kdfparams_pbkdf2_c_empty.json │ │ ├── kdfparams_pbkdf2_c_wrong.json │ │ ├── kdfparams_pbkdf2_salt_empty.json │ │ ├── kdfparams_pbkdf2_salt_wrong.json │ │ ├── kdfparams_salt_empty.json │ │ ├── kdfparams_salt_wrong.json │ │ ├── kdfparams_scrypt_p_empty.json │ │ ├── kdfparams_scrypt_r_empty.json │ │ ├── mac_empty.json │ │ └── mac_wrong.json │ ├── keystores │ │ ├── 02a55ab6-554a-4e78-bc26-6a7acced7e5e.json │ │ ├── 045861fe-0e9b-4069-92aa-0ac03cad55e0.json │ │ ├── 175169f7-5a35-4df7-93c1-1ff612168e71.json │ │ ├── 3831346d-0b81-405b-89cf-cdb1d010430e.json │ │ ├── 42c275c6-957a-49e8-9eb3-43c21cbf583f.json │ │ ├── 7f5406be-b5ee-4497-948c-877deab8c994.json │ │ └── identity.json │ ├── mnemonic.json │ ├── rlp.json │ ├── ttTransactionTest.json │ ├── ttTransactionTestEip155VitaliksTests.json │ ├── txs.json │ ├── v3-crypto-scrypt-1024.json │ ├── v3-incorrect-address.json │ ├── v3-incorrect-version.json │ ├── v3-invalid-ciper-params.json │ ├── v3-invalid-cipher.json │ ├── v3-invalid-kdf-params.json │ ├── v3-invalid-kdf.json │ ├── v3-pbkdf2-testpassword.json │ ├── v3-scrypt-testpassword.json │ ├── v3-unsupported-prf.json │ └── v3-wif.json ├── Foundation │ ├── AppErrorTests.swift │ ├── BIP44Tests.swift │ ├── Bitcoin │ │ ├── BTCKeyTests.swift │ │ ├── BTCTransactionSignerTests.swift │ │ └── BTCTransactionTests.swift │ ├── ChainTypeTests.swift │ ├── EOS │ │ ├── EOSKeyTests.swift │ │ └── EOSTransactionSignerTests.swift │ ├── Ethereum │ │ ├── ETHKeyTests.swift │ │ └── ETHTransactionTests.swift │ ├── KeyPairTests.swift │ ├── MnemonicTests.swift │ ├── MnemonicUtilTests.swift │ ├── NetworkTests.swift │ └── TransactionSignedResultTests.swift ├── Info.plist ├── Keystore │ ├── Bitcoin │ │ ├── BTCKeystoreTests.swift │ │ └── BTCMnemonicKeystoreTests.swift │ ├── CryptoTests.swift │ ├── EOS │ │ ├── EOSKeystoreTests.swift │ │ └── EOSLegacyKeystoreTests.swift │ ├── EncryptedMessageTests.swift │ ├── Ethereum │ │ ├── ETHKeystoreTests.swift │ │ └── ETHMnemonicKeystoreTests.swift │ ├── Identity │ │ └── IdentityKeystoreTests.swift │ ├── KDFPerformanceTests.swift │ ├── KeystoreTests.swift │ └── WalletMetaTests.swift ├── Storage │ ├── LocalFileStorageTests.swift │ └── StorageManagerTests.swift ├── TestCase.swift ├── TestHelper.swift ├── Utils │ ├── BigNumberTests.swift │ ├── DataExtensionTests.swift │ ├── HexTests.swift │ ├── RLPTests.swift │ ├── SigUtilTests.swift │ └── StringExtensionTests.swift ├── Validator │ ├── AddressValidatorTests.swift │ ├── EOSAccountNameValidatorTests.swift │ ├── IdentityValidatorTests.swift │ ├── MnemonicValidatorTests.swift │ ├── PasswordValidatorTests.swift │ ├── PrivateKeyValidatorTests.swift │ ├── V3KeystoreValidatorTests.swift │ └── WalletIDValidatorTests.swift └── Wallet │ ├── BitcoinWalletTests.swift │ ├── EthereumWalletTests.swift │ ├── IdentityTests.swift │ └── WalletManagerTests.swift ├── TokenCore.podspec ├── TokenCore.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── TokenCore.xcscheme │ └── TokenCoreTests.xcscheme ├── TokenCore.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist └── Vendor ├── CoreBitcoin ├── BTC256.h ├── BTC256.m ├── BTCAddress.h ├── BTCAddress.m ├── BTCAddressSubclass.h ├── BTCAssetAddress.h ├── BTCAssetAddress.m ├── BTCAssetID.h ├── BTCAssetID.m ├── BTCAssetType.h ├── BTCAssetType.m ├── BTCBase58.h ├── BTCBase58.m ├── BTCBigNumber.h ├── BTCBigNumber.m ├── BTCBitcoinURL.h ├── BTCBitcoinURL.m ├── BTCBlindSignature.h ├── BTCBlindSignature.m ├── BTCBlock.h ├── BTCBlock.m ├── BTCBlockHeader.h ├── BTCBlockHeader.m ├── BTCBlockchainInfo.h ├── BTCBlockchainInfo.m ├── BTCChainCom.h ├── BTCChainCom.m ├── BTCCurrencyConverter.h ├── BTCCurrencyConverter.m ├── BTCCurvePoint.h ├── BTCCurvePoint.m ├── BTCData.h ├── BTCData.m ├── BTCEncryptedBackup.h ├── BTCEncryptedBackup.m ├── BTCEncryptedMessage.h ├── BTCEncryptedMessage.m ├── BTCErrors.h ├── BTCErrors.m ├── BTCFancyEncryptedMessage.h ├── BTCFancyEncryptedMessage.m ├── BTCHashID.h ├── BTCHashID.m ├── BTCKey.h ├── BTCKey.m ├── BTCKeychain.h ├── BTCKeychain.m ├── BTCMerkleTree.h ├── BTCMerkleTree.m ├── BTCMnemonic.h ├── BTCMnemonic.m ├── BTCNetwork.h ├── BTCNetwork.m ├── BTCNumberFormatter.h ├── BTCNumberFormatter.m ├── BTCOpcode.h ├── BTCOpcode.m ├── BTCOutpoint.h ├── BTCOutpoint.m ├── BTCPaymentMethod.h ├── BTCPaymentMethod.m ├── BTCPaymentMethodDetails.h ├── BTCPaymentMethodDetails.m ├── BTCPaymentMethodRequest.h ├── BTCPaymentMethodRequest.m ├── BTCPaymentProtocol.h ├── BTCPaymentProtocol.m ├── BTCPaymentRequest.h ├── BTCPaymentRequest.m ├── BTCPriceSource.h ├── BTCPriceSource.m ├── BTCProcessor.h ├── BTCProcessor.m ├── BTCProtocolBuffers.h ├── BTCProtocolBuffers.m ├── BTCProtocolSerialization.h ├── BTCProtocolSerialization.m ├── BTCQRCode.h ├── BTCQRCode.m ├── BTCScript.h ├── BTCScript.m ├── BTCScriptMachine.h ├── BTCScriptMachine.m ├── BTCScriptTestData.h ├── BTCSecretSharing.h ├── BTCSecretSharing.m ├── BTCSignatureHashType.h ├── BTCTransaction.h ├── BTCTransaction.m ├── BTCTransactionBuilder.h ├── BTCTransactionBuilder.m ├── BTCTransactionInput.h ├── BTCTransactionInput.m ├── BTCTransactionOutput.h ├── BTCTransactionOutput.m ├── BTCUnitsAndLimits.h ├── CoreBitcoin.h ├── NS+BTCBase58.h ├── NS+BTCBase58.m ├── NSData+BTCData.h └── NSData+BTCData.m ├── libscrypt ├── LICENSE ├── Makefile ├── README.md ├── b64.c ├── b64.h ├── crypto-mcf.c ├── crypto-scrypt-saltgen.c ├── crypto_scrypt-check.c ├── crypto_scrypt-hash.c ├── crypto_scrypt-hexconvert.c ├── crypto_scrypt-hexconvert.h ├── crypto_scrypt-nosse.c ├── libscrypt.h ├── libscrypt.version ├── sha256.c ├── sha256.h ├── slowequals.c ├── slowequals.h └── sysendian.h └── secp256k1 └── secp256k1.framework ├── Documentation ├── Headers ├── Resources ├── Versions ├── A │ ├── A │ ├── Documentation │ │ └── Documentation │ ├── Headers │ │ ├── Headers │ │ ├── secp256k1.h │ │ └── secp256k1_recovery.h │ ├── Resources │ │ ├── Info.plist │ │ └── Resources │ └── secp256k1 └── Current └── secp256k1 /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | ## CocoaPods 36 | Pods/ 37 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - identifier_name 3 | - force_cast 4 | - force_try 5 | 6 | excluded: 7 | - Pods 8 | - Sources/Vendor 9 | - Tests 10 | - Example 11 | 12 | line_length: 180 13 | 14 | function_parameter_count: 10 15 | 16 | type_body_length: 17 | - 400 # warning 18 | - 600 # error 19 | 20 | 21 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, "11.2" 2 | use_modular_headers! 3 | 4 | project 'TokenCore.xcodeproj' 5 | target 'TokenCore_Example' do 6 | 7 | pod 'TokenCore', :path => '../' 8 | pod 'PureLayout' 9 | pod 'MBProgressHUD', '~> 1.1.0' 10 | pod 'Alamofire', '~> 5.0.0-beta.2' 11 | pod "CoreBitcoin", git: "https://github.com/consenlabs/token-core-ios-dep.git" 12 | 13 | # pod "TokenCore", git: "https://github.com/consenlabs/token-core-ios.git" 14 | end 15 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.0-beta.2) 3 | - BigInt (3.0.0): 4 | - SipHash (~> 1.2) 5 | - CoreBitcoin (0.0.1): 6 | - GRKOpenSSLFramework 7 | - CryptoSwift (0.9.0) 8 | - GRKOpenSSLFramework (1.0.2.14.1) 9 | - MBProgressHUD (1.1.0) 10 | - PureLayout (3.1.4) 11 | - secp256k1.swift (0.1.4) 12 | - SipHash (1.2.2) 13 | - TokenCore (0.1): 14 | - BigInt (= 3.0.0) 15 | - CoreBitcoin 16 | - CryptoSwift (= 0.9.0) 17 | - GRKOpenSSLFramework 18 | - secp256k1.swift 19 | 20 | DEPENDENCIES: 21 | - Alamofire (~> 5.0.0-beta.2) 22 | - CoreBitcoin (from `https://github.com/consenlabs/token-core-ios-dep.git`) 23 | - MBProgressHUD (~> 1.1.0) 24 | - PureLayout 25 | - TokenCore (from `../`) 26 | 27 | SPEC REPOS: 28 | https://github.com/cocoapods/specs.git: 29 | - Alamofire 30 | - BigInt 31 | - CryptoSwift 32 | - GRKOpenSSLFramework 33 | - MBProgressHUD 34 | - PureLayout 35 | - secp256k1.swift 36 | - SipHash 37 | 38 | EXTERNAL SOURCES: 39 | CoreBitcoin: 40 | :git: https://github.com/consenlabs/token-core-ios-dep.git 41 | TokenCore: 42 | :path: "../" 43 | 44 | CHECKOUT OPTIONS: 45 | CoreBitcoin: 46 | :commit: 48fd18897c7b067b073127ebefd1fbd756fcb66a 47 | :git: https://github.com/consenlabs/token-core-ios-dep.git 48 | 49 | SPEC CHECKSUMS: 50 | Alamofire: d1e5493588babe3e7b56ae29e8032942f4de09fe 51 | BigInt: a7864bcecd2976bced91963baef90079dbdcca25 52 | CoreBitcoin: 23bfc2e0c45106c5a39b240a6ce8f56c3b084ebf 53 | CryptoSwift: bca8c5b653dcc2d9734409242a070ff53bafac86 54 | GRKOpenSSLFramework: 845532a41bd75c6f5b99c9d95b25858357268a78 55 | MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 56 | PureLayout: f08c01b8dec00bb14a1fefa3de4c7d9c265df85e 57 | secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 58 | SipHash: fad90a4683e420c52ef28063063dbbce248ea6d4 59 | TokenCore: 4b00a181262f6559735bcac1b32af7c9af038002 60 | 61 | PODFILE CHECKSUM: da7a780239c061776cc84de188d57a2a8abfdb12 62 | 63 | COCOAPODS: 1.6.1 64 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/TokenCore.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TokenCore", 3 | "version": "0.1", 4 | "summary": "Blockchain Library for imToken", 5 | "description": "Token Core Library powering imToken iOS app.", 6 | "homepage": "https://token.im", 7 | "license": { 8 | "type": "Apache License, Version 2.0", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "James Chen": "james@ashchan.com" 13 | }, 14 | "platforms": { 15 | "ios": "9.0" 16 | }, 17 | "source": { 18 | "git": "https://github.com/consenlabs/ios-token-core.git", 19 | "tag": "0.1" 20 | }, 21 | "source_files": "Sources/**/*.{h,m,swift}", 22 | "swift_version": "4.0", 23 | "dependencies": { 24 | "CryptoSwift": [ 25 | "0.9.0" 26 | ], 27 | "BigInt": [ 28 | "3.0.0" 29 | ], 30 | "GRKOpenSSLFramework": [ 31 | 32 | ], 33 | "CoreBitcoin": [ 34 | 35 | ], 36 | "secp256k1.swift": [ 37 | 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.0.0-beta.2) 3 | - BigInt (3.0.0): 4 | - SipHash (~> 1.2) 5 | - CoreBitcoin (0.0.1): 6 | - GRKOpenSSLFramework 7 | - CryptoSwift (0.9.0) 8 | - GRKOpenSSLFramework (1.0.2.14.1) 9 | - MBProgressHUD (1.1.0) 10 | - PureLayout (3.1.4) 11 | - secp256k1.swift (0.1.4) 12 | - SipHash (1.2.2) 13 | - TokenCore (0.1): 14 | - BigInt (= 3.0.0) 15 | - CoreBitcoin 16 | - CryptoSwift (= 0.9.0) 17 | - GRKOpenSSLFramework 18 | - secp256k1.swift 19 | 20 | DEPENDENCIES: 21 | - Alamofire (~> 5.0.0-beta.2) 22 | - CoreBitcoin (from `https://github.com/consenlabs/token-core-ios-dep.git`) 23 | - MBProgressHUD (~> 1.1.0) 24 | - PureLayout 25 | - TokenCore (from `../`) 26 | 27 | SPEC REPOS: 28 | https://github.com/cocoapods/specs.git: 29 | - Alamofire 30 | - BigInt 31 | - CryptoSwift 32 | - GRKOpenSSLFramework 33 | - MBProgressHUD 34 | - PureLayout 35 | - secp256k1.swift 36 | - SipHash 37 | 38 | EXTERNAL SOURCES: 39 | CoreBitcoin: 40 | :git: https://github.com/consenlabs/token-core-ios-dep.git 41 | TokenCore: 42 | :path: "../" 43 | 44 | CHECKOUT OPTIONS: 45 | CoreBitcoin: 46 | :commit: 48fd18897c7b067b073127ebefd1fbd756fcb66a 47 | :git: https://github.com/consenlabs/token-core-ios-dep.git 48 | 49 | SPEC CHECKSUMS: 50 | Alamofire: d1e5493588babe3e7b56ae29e8032942f4de09fe 51 | BigInt: a7864bcecd2976bced91963baef90079dbdcca25 52 | CoreBitcoin: 23bfc2e0c45106c5a39b240a6ce8f56c3b084ebf 53 | CryptoSwift: bca8c5b653dcc2d9734409242a070ff53bafac86 54 | GRKOpenSSLFramework: 845532a41bd75c6f5b99c9d95b25858357268a78 55 | MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 56 | PureLayout: f08c01b8dec00bb14a1fefa3de4c7d9c265df85e 57 | secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 58 | SipHash: fad90a4683e420c52ef28063063dbbce248ea6d4 59 | TokenCore: 4b00a181262f6559735bcac1b32af7c9af038002 60 | 61 | PODFILE CHECKSUM: da7a780239c061776cc84de188d57a2a8abfdb12 62 | 63 | COCOAPODS: 1.6.1 64 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TokenCore/TokenCore.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/TokenCore 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/GRKOpenSSLFramework/OpenSSL-iOS/bin" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/TokenCore" "${PODS_ROOT}/Headers/Public" 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/BigInt/BigInt.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/SipHash/SipHash.modulemap" -fmodule-map-file="${PODS_ROOT}/Headers/Public/CoreBitcoin/CoreBitcoin.modulemap" -fmodule-map-file="${PODS_ROOT}/Headers/Public/secp256k1/secp256k1.swift.modulemap" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/BigInt/BigInt.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift/CryptoSwift.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/SipHash/SipHash.modulemap" -Xcc -fmodule-map-file="${PODS_ROOT}/Headers/Public/CoreBitcoin/CoreBitcoin.modulemap" -Xcc -fmodule-map-file="${PODS_ROOT}/Headers/Public/secp256k1/secp256k1.swift.modulemap" -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 11 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 12 | SKIP_INSTALL = YES 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BigInt" "${PODS_CONFIGURATION_BUILD_DIR}/CryptoSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SipHash" 14 | -------------------------------------------------------------------------------- /Example/TokenCore.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/TokenCore.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/TokenCore/AppState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppState.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2018/11/2. 6 | // Copyright © 2018 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class AppState { 13 | 14 | public static let shared = AppState() 15 | 16 | var mnemonic: String? 17 | var walletIds: [String]? 18 | let defaultPassword: String = "88888888" 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Example/TokenCore/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2018/11/2. 6 | // Copyright © 2018 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Constants { 12 | static public let password = "Insecure Pa55w0rd" 13 | static public let testMnemonic = "inject kidney empty canal shadow pact comfort wife crush horse wife sketch" 14 | static public let testWif = "cT4fTJyLd5RmSZFHnkGmVCzXDKuJLbyTt7cy77ghTTCagzNdPH1j" 15 | // 19e052557667896a701af72cdb5b81ed0b0a417951f7f0ac730d901c2087db7f 16 | static public let testPrivateKey = "19e052557667896a701af72cdb5b81ed0b0a417951f7f0ac730d901c2087db7f" 17 | static public let toAddress = "0xEAC1a91E4E847c92161bF6DFFba23e8499d46A3e" 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Example/TokenCore/Images.xcassets/AppIcon.appiconset/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/consenlabs/token-core-ios/b896f0cacb9530894cd18ec3843c4ca630d8a867/Example/TokenCore/Images.xcassets/AppIcon.appiconset/AppIcon.png -------------------------------------------------------------------------------- /Example/TokenCore/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "size" : "60x60", 40 | "idiom" : "iphone", 41 | "filename" : "AppIcon.png", 42 | "scale" : "3x" 43 | }, 44 | { 45 | "idiom" : "ios-marketing", 46 | "size" : "1024x1024", 47 | "scale" : "1x" 48 | } 49 | ], 50 | "info" : { 51 | "version" : 1, 52 | "author" : "xcode" 53 | } 54 | } -------------------------------------------------------------------------------- /Example/TokenCore/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/TokenCore/Images.xcassets/info.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "info.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/TokenCore/Images.xcassets/info.imageset/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/consenlabs/token-core-ios/b896f0cacb9530894cd18ec3843c4ca630d8a867/Example/TokenCore/Images.xcassets/info.imageset/info.png -------------------------------------------------------------------------------- /Example/TokenCore/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/TokenCore/LayoutViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LayoutViewController.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2018/11/5. 6 | // Copyright © 2018 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import PureLayout 11 | 12 | class LayoutViewController: UIViewController { 13 | 14 | var didSetupConstraints = false 15 | 16 | override func loadView() { 17 | view = UIView() 18 | self.fillViews() 19 | view.setNeedsUpdateConstraints() 20 | } 21 | 22 | func fillViews() { 23 | assertionFailure("This shoud be implemented in subclass") 24 | } 25 | 26 | override func updateViewConstraints() { 27 | if !didSetupConstraints { 28 | self.fillViewConstraints() 29 | didSetupConstraints = true 30 | } 31 | super.updateViewConstraints() 32 | } 33 | 34 | func fillViewConstraints() { 35 | assertionFailure("This shoud be implemented in subclass") 36 | } 37 | 38 | static func createButton(_ text: String) -> UIButton { 39 | let btn = UIButton.init(type: .system) 40 | btn.configureForAutoLayout() 41 | btn.setTitle(text, for: .normal) 42 | return btn 43 | } 44 | 45 | 46 | 47 | override func viewDidLoad() { 48 | super.viewDidLoad() 49 | 50 | // Do any additional setup after loading the view. 51 | } 52 | 53 | 54 | /* 55 | // MARK: - Navigation 56 | 57 | // In a storyboard-based application, you will often want to do a little preparation before navigation 58 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 59 | // Get the new view controller using segue.destination. 60 | // Pass the selected object to the new view controller. 61 | } 62 | */ 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Example/TokenCore/NetworkUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkUtil.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2019/3/4. 6 | // Copyright © 2019 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | class NetworkUtil { 13 | public static func get(_ url: String) -> String { 14 | var result: String = "" 15 | let semaphore = DispatchSemaphore(value: 0) 16 | AF.request(url).responseJSON { response in 17 | print("Request: \(String(describing: response.request))") // original url request 18 | print("Response: \(String(describing: response.response))") // http url response 19 | print("Result: \(response.result)") // response serialization result 20 | 21 | 22 | if let json = response.result.value { 23 | print("JSON: \(json)") // serialized json response 24 | } 25 | 26 | if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) { 27 | print("Data: \(utf8Text)") // original server data as UTF8 string 28 | result = utf8Text 29 | } 30 | semaphore.signal() 31 | } 32 | _ = semaphore.wait(timeout: .now() + 10) 33 | return result 34 | } 35 | 36 | public static func post(_ url: String, body: Parameters) -> String { 37 | var result: String = "" 38 | let semaphore = DispatchSemaphore(value: 0) 39 | AF.request(url, method: .post, parameters: body, encoding: JSONEncoding.default).responseJSON { response in 40 | print("Request: \(String(describing: response.request))") // original url request 41 | print("Response: \(String(describing: response.response))") // http url response 42 | print("Result: \(response.result)") // response serialization result 43 | 44 | 45 | if let json = response.result.value { 46 | print("JSON: \(json)") // serialized json response 47 | } 48 | 49 | if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) { 50 | print("Data: \(utf8Text)") // original server data as UTF8 string 51 | result = utf8Text 52 | } 53 | semaphore.signal() 54 | } 55 | _ = semaphore.wait(timeout: .now() + 10) 56 | return result 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example/TokenCore/ResultController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultController.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2019/2/28. 6 | // Copyright © 2019 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ResultController: UIViewController { 12 | 13 | var info: String! 14 | 15 | @IBOutlet weak var textView: UITextView! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | // Do any additional setup after loading the view. 21 | self.navigationItem.title = "Result" 22 | textView.text = info 23 | print("Result:\n\(info)") 24 | } 25 | 26 | 27 | /* 28 | // MARK: - Navigation 29 | 30 | // In a storyboard-based application, you will often want to do a little preparation before navigation 31 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 32 | // Get the new view controller using segue.destination. 33 | // Pass the selected object to the new view controller. 34 | } 35 | */ 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Example/TokenCore/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // TokenCore_Example 4 | // 5 | // Created by xyz on 2018/11/2. 6 | // Copyright © 2018 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import TokenCore 11 | 12 | func prettyPrintJSON(_ obj: JSONObject) -> String { 13 | // fail fast in demo 14 | let encoded = try! JSONSerialization.data(withJSONObject: obj, options: .prettyPrinted) 15 | return String(data: encoded, encoding: .utf8)! 16 | } 17 | -------------------------------------------------------------------------------- /Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | module libscrypt [system][extern_c] { 2 | header "../Vendor/libscrypt/libscrypt.h" 3 | export * 4 | } 5 | 6 | module libsecp256k1 [system][extern_c] { 7 | header "../Vendor/secp256k1/secp256k1.framework/Headers/secp256k1.h" 8 | header "../Vendor/secp256k1/secp256k1.framework/Headers/secp256k1_recovery.h" 9 | export * 10 | } 11 | 12 | /// On macOS 10.14 and above, install /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg 13 | /// to have /usr/include headers. 14 | module CCommonCrypto { 15 | header "/usr/include/CommonCrypto/CommonCrypto.h" 16 | export * 17 | } 18 | 19 | module CoreBitcoin [system] { 20 | header "../Vendor/CoreBitcoin/CoreBitcoin.h" 21 | header "../Vendor/CoreBitcoin/NSData+BTCData.h" 22 | header "../Vendor/CoreBitcoin/NS+BTCBase58.h" 23 | export * 24 | } 25 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, "9.3" 2 | 3 | target "TokenCore" do 4 | use_frameworks! 5 | 6 | pod "CryptoSwift", ">= 0.10.0" 7 | pod "BigInt", "3.0.0" 8 | pod "GRKOpenSSLFramework" 9 | 10 | pod 'SwiftLint' 11 | 12 | target "TokenCoreTests" do 13 | inherit! :search_paths 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - BigInt (3.0.0): 3 | - SipHash (~> 1.2) 4 | - CryptoSwift (0.13.0) 5 | - GRKOpenSSLFramework (1.0.2.13) 6 | - SipHash (1.2.0) 7 | - SwiftLint (0.27.0) 8 | 9 | DEPENDENCIES: 10 | - BigInt (= 3.0.0) 11 | - CryptoSwift (>= 0.10.0) 12 | - GRKOpenSSLFramework 13 | - SwiftLint 14 | 15 | SPEC REPOS: 16 | https://github.com/cocoapods/specs.git: 17 | - BigInt 18 | - CryptoSwift 19 | - GRKOpenSSLFramework 20 | - SipHash 21 | - SwiftLint 22 | 23 | SPEC CHECKSUMS: 24 | BigInt: a7864bcecd2976bced91963baef90079dbdcca25 25 | CryptoSwift: 16e78bebf567bad1c87b2d58f6547f25b74c31aa 26 | GRKOpenSSLFramework: aee21fe0d6ab76fefa4f2db599d11b9c3a53c43b 27 | SipHash: c6e9e43e9c531b5bc6602545130c26194a6d31ce 28 | SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073 29 | 30 | PODFILE CHECKSUM: 09216d093d2b0735356766f1b476d7b7d14cb574 31 | 32 | COCOAPODS: 1.5.3 33 | -------------------------------------------------------------------------------- /Sources/Encryptor/AES128.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AES128.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/25. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CryptoSwift 11 | 12 | extension Encryptor { 13 | class AES128 { 14 | // swiftlint:disable nesting 15 | enum Mode { 16 | case ctr 17 | case cbc 18 | } 19 | 20 | private let key: String 21 | private let iv: String 22 | private let mode: Mode 23 | private let padding: Padding 24 | 25 | // Key and iv both should be in hex format 26 | init(key: String, iv: String, mode: Mode = .ctr, padding: Padding = .noPadding) { 27 | self.key = key 28 | self.iv = iv 29 | self.mode = mode 30 | self.padding = padding 31 | } 32 | 33 | func encrypt(string: String) -> String { 34 | return encrypt(hex: string.tk_toHexString()) 35 | } 36 | 37 | // Encrypt input hex string and return encrypted string in hex format 38 | func encrypt(hex: String) -> String { 39 | if let aes = aes { 40 | let inputBytes = [UInt8].init(hex: hex) 41 | let encrypted = try! aes.encrypt(inputBytes) 42 | return Data(bytes: encrypted).tk_toHexString() 43 | } else { 44 | return "" 45 | } 46 | } 47 | 48 | // Decrypt input hex string and return decrypted string in hex format 49 | func decrypt(hex: String) -> String { 50 | if let aes = aes { 51 | let inputBytes = [UInt8].init(hex: hex) 52 | let decrypted = try! aes.decrypt(inputBytes) 53 | return Data(bytes: decrypted).tk_toHexString() 54 | } else { 55 | return "" 56 | } 57 | } 58 | 59 | private var aes: AES? { 60 | let keyBytes = [UInt8].init(hex: key) 61 | let ivBytes = [UInt8].init(hex: iv) 62 | 63 | return try? AES(key: keyBytes, blockMode: blockMode(iv: ivBytes), padding: self.padding) 64 | } 65 | 66 | private func blockMode(iv: [UInt8]) -> BlockMode { 67 | switch mode { 68 | case .cbc: 69 | return .CBC(iv: iv) 70 | default: 71 | return .CTR(iv: iv) 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Sources/Encryptor/Encryptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Encryptor.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/25. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Encryptor { 12 | 13 | // ETH uses these core encryption algorithems 14 | // * PBKDF2 15 | // * SCRYPT 16 | // * AES-128 (Modes: CTR, CBC) 17 | // * SECP256K1 18 | // * SHA3 (Keccak-256) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Sources/Encryptor/Hash.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Hash.swift 3 | // token 4 | // 5 | // Created by James Chen on 2018/03/06. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CryptoSwift 11 | import CoreBitcoin 12 | 13 | extension Encryptor { 14 | class Hash { 15 | static func hmacSHA256(key: Data, data: Data) -> Data { 16 | if let hmac = try? HMAC(key: Array(key), variant: .sha256).authenticate(Array(data)) { 17 | return Data(bytes: hmac) 18 | } else { 19 | return Data() 20 | } 21 | } 22 | 23 | /// Only for calculating merkle root hash for Identity backup. 24 | static func merkleRoot(cipherData: Data) -> Data { 25 | let length = cipherData.count 26 | var items = [Data]() 27 | var i = 0 28 | while i < length { 29 | items.append(cipherData.subdata(in: i..<(i + min(length - i, 1024)))) 30 | i += 1024 31 | } 32 | 33 | return BTCMerkleTree(dataItems: items).merkleRoot 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Encryptor/Keccak256.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Keccak256.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/26. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CryptoSwift 11 | 12 | public extension Encryptor { 13 | public class Keccak256 { 14 | public init() {} 15 | 16 | // Encrypt and return as hex 17 | public func encrypt(hex: String) -> String { 18 | return encrypt(data: hex.tk_dataFromHexString()!) 19 | } 20 | 21 | public func encrypt(data: Data) -> String { 22 | return SHA3(variant: .keccak256).calculate(for: data.bytes).toHexString() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Encryptor/PBKDF2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PBKDF2.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/25. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CryptoSwift 11 | 12 | extension Encryptor { 13 | class PBKDF2 { 14 | private let password: String 15 | private let salt: String 16 | private let iterations: Int 17 | private let keyLength: Int 18 | 19 | // Param password and salt salt should be in hex format. 20 | init(password: String, salt: String, iterations: Int, keyLength: Int = 32) { 21 | self.password = password 22 | self.salt = salt 23 | self.iterations = iterations 24 | self.keyLength = keyLength 25 | } 26 | 27 | // Encrypt input string and return encrypted string in hex format. 28 | func encrypt() -> String { 29 | let saltBytes = [UInt8](hex: salt) 30 | let passwordBytes = password.data(using: .utf8)!.bytes 31 | if let pbkdf2 = try? PKCS5.PBKDF2(password: passwordBytes, salt: saltBytes, iterations: iterations, keyLength: keyLength) { 32 | if let encrypted = try? pbkdf2.calculate() { 33 | return Data(bytes: encrypted).tk_toHexString() 34 | } 35 | } 36 | 37 | return "" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Encryptor/Scrypt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scrypt.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/25. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin.libscrypt 11 | 12 | extension Encryptor { 13 | class Scrypt { 14 | private let password: String 15 | private let salt: String 16 | private let n: Int 17 | private let r: Int 18 | private let p: Int 19 | private let dklen = 32 20 | 21 | // Param: password and salt should be in hex format. 22 | init(password: String, salt: String, n: Int, r: Int, p: Int) { 23 | self.password = password 24 | self.salt = salt 25 | self.n = n 26 | self.r = r 27 | self.p = p 28 | } 29 | 30 | func encrypt() -> String { 31 | let passwordBytes = password.data(using: .utf8)!.bytes 32 | let saltBytes = salt.tk_dataFromHexString()!.bytes 33 | 34 | var data = Data(count: dklen) 35 | data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in 36 | libscrypt_scrypt( 37 | passwordBytes, 38 | passwordBytes.count, 39 | saltBytes, 40 | saltBytes.count, 41 | UInt64(n), 42 | UInt32(r), 43 | UInt32(p), 44 | bytes, 45 | dklen 46 | ) 47 | } 48 | return data.tk_toHexString() 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Foundation/BIP44.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BIP44.swift 3 | // token 4 | // 5 | // Created by Kai Chen on 17/11/2017. 6 | // Copyright © 2017 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct BIP44 { 12 | public static let eth = "m/44'/60'/0'/0/0" 13 | public static let ipfs = "m/44'/99'/0'" 14 | public static let btcMainnet = "m/44'/0'/0'" 15 | public static let btcTestnet = "m/44'/1'/0'" 16 | public static let btcSegwitMainnet = "m/49'/0'/0'" 17 | public static let btcSegwitTestnet = "m/49'/1'/0'" 18 | public static let eos = "m/44'/194'" 19 | // public static let slip48 = "m/48'/4'/0'/0'/0',m/48'/4'/1'/0'/0'" 20 | public static let eosLedger = "m/44'/194'/0'/0/0" 21 | 22 | static func path(for network: Network?, segWit: SegWit) -> String { 23 | let isMainnet = network?.isMainnet ?? true 24 | if isMainnet { 25 | if segWit.isSegWit { 26 | return BIP44.btcSegwitMainnet 27 | } else { 28 | return BIP44.btcMainnet 29 | } 30 | } else { 31 | if segWit.isSegWit { 32 | return BIP44.btcSegwitTestnet 33 | } else { 34 | return BIP44.btcTestnet 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Foundation/Bitcoin/BTCKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BTCKey.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/05/16. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | public extension BTCKey { 13 | public func address(on network: Network?, segWit: SegWit) -> BTCAddress { 14 | if segWit.isSegWit { 15 | if isMainnet(network) { 16 | return witnessAddress 17 | } else { 18 | return witnessAddressTestnet 19 | } 20 | } else { 21 | if isMainnet(network) { 22 | return address 23 | } else { 24 | return addressTestnet 25 | } 26 | } 27 | } 28 | 29 | private func isMainnet(_ network: Network?) -> Bool { 30 | if let network = network { 31 | return network.isMainnet 32 | } 33 | return true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Foundation/Bitcoin/SegWit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SegWit.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/05/16. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum SegWit: String { 12 | case none = "NONE" 13 | case p2wpkh = "P2WPKH" 14 | 15 | public var isSegWit: Bool { 16 | return self == .p2wpkh 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Foundation/ChainType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChainType.swift 3 | // token 4 | // 5 | // Created by Kai Chen on 08/09/2017. 6 | // Copyright © 2017 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum ChainType: String { 12 | case eth = "ETHEREUM" 13 | case btc = "BITCOIN" 14 | case eos = "EOS" 15 | 16 | public var privateKeySource: WalletMeta.Source { 17 | if self == .eth { 18 | return .privateKey 19 | } 20 | return .wif 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/Foundation/EOS/EOSKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSKey.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/06/21. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | class EOSKey { 13 | private let btcKey: BTCKey 14 | 15 | var publicKey: String { 16 | let publicKey = btcKey.compressedPublicKey as Data 17 | let checksum = (BTCRIPEMD160(publicKey) as Data).bytes[0..<4] 18 | let base58 = BTCBase58StringWithData(publicKey + checksum)! 19 | return "EOS" + base58 20 | } 21 | 22 | var wif: String { 23 | return btcKey.wif 24 | } 25 | 26 | init(privateKey: [UInt8]) { 27 | btcKey = BTCKey(privateKey: Data(bytes: privateKey))! 28 | } 29 | 30 | init(key: BTCKey) { 31 | btcKey = key 32 | } 33 | 34 | convenience init(wif: String) { 35 | self.init(privateKey: EOSKey.privateKey(from: wif)) 36 | } 37 | 38 | func sign(data: Data) -> Data { 39 | return btcKey.eosCompactSignature(forHash: data) 40 | } 41 | 42 | 43 | public static func ecRecover(data: Data, signature: Data) throws -> String { 44 | guard let key = BTCKey.eosEcRecover(signature, forHash: data) else { 45 | throw "Not found a workable private key" 46 | } 47 | return EOSKey(key: key).publicKey 48 | } 49 | 50 | static func privateKey(from wif: String) -> [UInt8] { 51 | let wifBytes = (BTCDataFromBase58(wif) as Data).bytes 52 | return [UInt8].init(wifBytes[1.. Bool { 21 | return lhs.hash == rhs.hash && lhs.signs == rhs.signs 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/Foundation/EOS/EOSTransactionSigner.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSTransactionSigner.swift 3 | // TokenCore 4 | // 5 | // Created by xyz on 2018/5/26. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | class EOSTransactionSigner { 13 | private let txs: [EOSTransaction] 14 | private let keystore: Keystore 15 | private let password: String 16 | 17 | init(txs: [EOSTransaction], keystore: Keystore, password: String) { 18 | self.txs = txs 19 | self.keystore = keystore 20 | self.password = password 21 | } 22 | 23 | public func sign() throws -> [EOSSignResult] { 24 | guard keystore.verify(password: password) else { 25 | throw PasswordError.incorrect 26 | } 27 | 28 | return try txs.map { tx -> EOSSignResult in 29 | return try tx.sign(password: password, keystore: keystore) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Foundation/Ethereum/ETHKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ETHKey.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/24. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | public class ETHKey { 13 | private let rootPrivateKey: String 14 | let privateKey: String // For user daily use, adress/privateKey, via path "m/44'/60'/0'/0/index" 15 | var address: String { 16 | let btcKey = BTCKey(privateKey: privateKey.tk_dataFromHexString())! 17 | return ETHKey.pubToAddress(btcKey.uncompressedPublicKey as Data) 18 | } 19 | 20 | init(privateKey: String) { 21 | rootPrivateKey = "" 22 | self.privateKey = privateKey 23 | } 24 | 25 | init(seed: Data, path: String) { 26 | let rootKeychain = BTCKeychain(seed: seed)! 27 | rootPrivateKey = rootKeychain.extendedPrivateKey.tk_toHexString() 28 | let components = path.components(separatedBy: "/") 29 | let index = UInt32(components.last!)! 30 | let account = rootKeychain.derivedKeychain(withPath: components.dropLast().joined(separator: "/"))! 31 | privateKey = (account.key(at: index).privateKey as Data).tk_toHexString() 32 | } 33 | 34 | convenience init(mnemonic: Mnemonic, path: String) { 35 | let seed = ETHMnemonic.deterministicSeed(from: mnemonic) 36 | self.init(seed: seed.tk_dataFromHexString()!, path: path) 37 | } 38 | 39 | public static func mnemonicToAddress(_ mnemonic: Mnemonic, path: String) -> String { 40 | return ETHKey(mnemonic: mnemonic, path: path).address 41 | } 42 | 43 | public static func pubToAddress(_ publicKey: Data) -> String { 44 | let stringToEncrypt = publicKey.tk_toHexString().tk_substring(from: 2) 45 | let sha3Keccak = Encryptor.Keccak256().encrypt(hex: stringToEncrypt) 46 | return sha3Keccak.tk_substring(from: 24) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Foundation/KeyPair.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeyPair.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/06/21. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct KeyPair: Equatable { 12 | public let privateKey: String 13 | public let publicKey: String 14 | 15 | public static func == (lhs: KeyPair, rhs: KeyPair) -> Bool { 16 | return lhs.privateKey == rhs.privateKey && lhs.publicKey == rhs.publicKey 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Foundation/MnemonicUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MnemonicUtil.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/5. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | struct MnemonicUtil { 13 | static func btcMnemonicFromEngWords(_ words: String) -> BTCMnemonic { 14 | return BTCMnemonic(words: words.split(separator: " "), password: "", wordListType: BTCMnemonicWordListType.english)! 15 | } 16 | 17 | static func generateMnemonic() -> String { 18 | let entropy = Data.tk_random(of: 16) 19 | let words = BTCMnemonic(entropy: entropy, password: "", wordListType: .english).words as! [String] 20 | return words.joined(separator: " ") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Sources/Foundation/Network.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Network.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/03/28. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum Network: String { 12 | case mainnet = "MAINNET" 13 | case testnet = "TESTNET" 14 | 15 | var isMainnet: Bool { 16 | return self == .mainnet 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Foundation/TransactionSignedResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TransactionSignedResult.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/22. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct TransactionSignedResult { 12 | public let signedTx: String 13 | public let txHash: String 14 | public let wtxID: String 15 | 16 | init(signedTx: String, txHash: String, wtxID: String) { 17 | self.signedTx = signedTx 18 | self.txHash = txHash 19 | self.wtxID = wtxID 20 | } 21 | 22 | init(signedTx: String, txHash: String) { 23 | self.init(signedTx: signedTx, txHash: txHash, wtxID: "") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/Keystore/Bitcoin/BTCKeystore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BTCKeystore.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/3. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | struct BTCKeystore: Keystore, WIFCrypto { 13 | let id: String 14 | let version = 3 15 | var address: String 16 | let crypto: Crypto 17 | var meta: WalletMeta 18 | 19 | // Import with private key (WIF). 20 | init(password: String, wif: String, metadata: WalletMeta, id: String? = nil) throws { 21 | let privateKey = try PrivateKeyValidator(wif, on: .btc, network: metadata.network, requireCompressed: metadata.isSegWit).validate() 22 | 23 | let key = BTCKey(wif: wif)! 24 | address = key.address(on: metadata.network, segWit: metadata.segWit).string 25 | 26 | crypto = Crypto(password: password, privateKey: privateKey.tk_toHexString()) 27 | self.id = id ?? BTCKeystore.generateKeystoreId() 28 | meta = metadata 29 | } 30 | 31 | // MARK: - JSON 32 | init(json: JSONObject) throws { 33 | guard 34 | let cryptoJson = (json["crypto"] as? JSONObject) ?? (json["Crypto"] as? JSONObject), 35 | json["version"] as? Int == version 36 | else { 37 | throw KeystoreError.invalid 38 | } 39 | 40 | id = (json["id"] as? String) ?? BTCKeystore.generateKeystoreId() 41 | address = json["address"] as? String ?? "" 42 | crypto = try Crypto(json: cryptoJson) 43 | 44 | if let metaJSON = json[WalletMeta.key] as? JSONObject { 45 | meta = try WalletMeta(json: metaJSON) 46 | } else { 47 | meta = WalletMeta(chain: .btc, source: .keystore) 48 | } 49 | } 50 | 51 | func decryptWIF(_ password: String) -> String { 52 | let wif = crypto.privateKey(password: password).tk_fromHexString() 53 | let key = BTCKey(wif: wif)! 54 | return meta.isMainnet ? key.wif : key.wifTestnet 55 | } 56 | 57 | func serializeToMap() -> [String: Any] { 58 | return [ 59 | "id": id, 60 | "address": address, 61 | "createdAt": (Int)(meta.timestamp), 62 | "source": meta.source.rawValue, 63 | "chainType": meta.chain!.rawValue, 64 | "segWit": meta.segWit.rawValue 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Keystore/EOS/EOSLegacyKeystore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSLegacyKeystore.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/06/20. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | // Legacy keystore format pre-mainnet launch. 13 | struct EOSLegacyKeystore: Keystore, WIFCrypto { 14 | let id: String 15 | let version = 3 16 | var address: String 17 | let crypto: Crypto 18 | var meta: WalletMeta 19 | 20 | // Import with private key (WIF). 21 | init(password: String, wif: String, metadata: WalletMeta, accountName: String, id: String? = nil) throws { 22 | address = accountName 23 | crypto = Crypto(password: password, privateKey: wif.tk_toHexString()) 24 | self.id = id ?? EOSKeystore.generateKeystoreId() 25 | meta = metadata 26 | } 27 | 28 | // MARK: - JSON 29 | init(json: JSONObject) throws { 30 | guard 31 | let cryptoJson = (json["crypto"] as? JSONObject) ?? (json["Crypto"] as? JSONObject), 32 | json["version"] as? Int == version 33 | else { 34 | throw KeystoreError.invalid 35 | } 36 | 37 | id = (json["id"] as? String) ?? EOSKeystore.generateKeystoreId() 38 | address = json["address"] as? String ?? "" 39 | crypto = try Crypto(json: cryptoJson) 40 | 41 | if let metaJSON = json[WalletMeta.key] as? JSONObject { 42 | meta = try WalletMeta(json: metaJSON) 43 | } else { 44 | meta = WalletMeta(chain: .btc, source: .keystore) 45 | } 46 | } 47 | 48 | func decryptWIF(_ password: String) -> String { 49 | let wif = crypto.privateKey(password: password).tk_fromHexString() 50 | let key = BTCKey(wif: wif)! 51 | return key.wif 52 | } 53 | 54 | func exportPrivateKeys(_ password: String) -> [KeyPair] { 55 | let wif = crypto.privateKey(password: password).tk_fromHexString() 56 | let key = BTCKey(wif: wif)! 57 | let eosKey = EOSKey(wif: key.wif) 58 | let keyPair = KeyPair(privateKey: key.wif, publicKey: eosKey.publicKey) 59 | return [keyPair] 60 | } 61 | 62 | func serializeToMap() -> [String: Any] { 63 | return [ 64 | "id": id, 65 | "address": address, 66 | "createdAt": (Int)(meta.timestamp), 67 | "source": meta.source.rawValue, 68 | "chainType": meta.chain!.rawValue 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Sources/Keystore/EOS/EOSPermission.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSPermission.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/06/20. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct EOS { 12 | struct Permission { 13 | static let owner = "owner" 14 | static let active = "active" 15 | } 16 | 17 | public struct PermissionObject { 18 | public var permission: String 19 | public var publicKey: String 20 | public var parent: String 21 | 22 | public init(permission: String, publicKey: String, parent: String) { 23 | self.permission = permission 24 | self.publicKey = publicKey 25 | self.parent = parent 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/Keystore/EncryptedMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EncryptedMessage.swfit 3 | // token 4 | // 5 | // Created by Kai Chen on 20/11/2017. 6 | // Copyright © 2017 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // Store anything like { encStr: "secertMessage", nonce: "randomBytes" } 12 | struct EncryptedMessage { 13 | let encStr: String 14 | let nonce: String 15 | 16 | init(encStr: String, nonce: String) { 17 | self.encStr = encStr 18 | self.nonce = nonce 19 | } 20 | 21 | init?(json: JSONObject) { 22 | guard let encStr = json["encStr"] as? String, let nonce = json["nonce"] as? String else { 23 | return nil 24 | } 25 | self.init(encStr: encStr, nonce: nonce) 26 | } 27 | 28 | static func create(crypto: Crypto, password: String, message: String, nonce: String? = nil) -> EncryptedMessage { 29 | return create(crypto: crypto, derivedKey: crypto.derivedKey(with: password), message: message, nonce: nonce) 30 | } 31 | 32 | static func create(crypto: Crypto, derivedKey: String, message: String, nonce: String? = nil) -> EncryptedMessage { 33 | let nonceWithFallback = nonce ?? RandomIV().value 34 | let encryptor = crypto.encryptor(from: derivedKey.tk_substring(to: 32), nonce: nonceWithFallback) 35 | return EncryptedMessage(encStr: encryptor.encrypt(hex: message), nonce: nonceWithFallback) 36 | } 37 | 38 | // use kdf with password to decrypt secert message 39 | func decrypt(crypto: Crypto, password: String) -> String { 40 | let dk = crypto.derivedKey(with: password) 41 | let encryptor = crypto.encryptor(from: dk.tk_substring(to: 32), nonce: nonce) 42 | return encryptor.decrypt(hex: encStr) 43 | } 44 | 45 | func toJSON() -> JSONObject { 46 | return [ 47 | "encStr": encStr, 48 | "nonce": nonce 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Keystore/Ethereum/ETHKeystore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ETHKeystore.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/3. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ETHKeystore: ExportableKeystore, PrivateKeyCrypto { 12 | let id: String 13 | let version = 3 14 | var address: String 15 | let crypto: Crypto 16 | var meta: WalletMeta 17 | 18 | // Import from private key 19 | init(password: String, privateKey: String, metadata: WalletMeta, id: String? = nil) throws { 20 | address = ETHKey(privateKey: privateKey).address 21 | crypto = Crypto(password: password, privateKey: privateKey) 22 | self.id = id ?? ETHKeystore.generateKeystoreId() 23 | meta = metadata 24 | } 25 | 26 | // MARK: - JSON 27 | init(json: JSONObject) throws { 28 | guard 29 | let cryptoJson = (json["crypto"] as? JSONObject) ?? (json["Crypto"] as? JSONObject), 30 | json["version"] as? Int == version 31 | else { 32 | throw KeystoreError.invalid 33 | } 34 | 35 | id = (json["id"] as? String) ?? ETHKeystore.generateKeystoreId() 36 | address = json["address"] as? String ?? "" 37 | crypto = try Crypto(json: cryptoJson) 38 | 39 | if let metaJSON = json[WalletMeta.key] as? JSONObject { 40 | meta = try WalletMeta(json: metaJSON) 41 | } else { 42 | meta = WalletMeta(chain: .eth, source: .keystore) 43 | } 44 | } 45 | 46 | func serializeToMap() -> [String: Any] { 47 | return [ 48 | "id": id, 49 | "address": address, 50 | "createdAt": (Int)(meta.timestamp), 51 | "source": meta.source.rawValue, 52 | "chainType": meta.chain!.rawValue 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Keystore/JSONObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JSONObject.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/03/28. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public typealias JSONObject = [String: Any] 12 | -------------------------------------------------------------------------------- /Sources/Keystore/RandomIV.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RandomIV.swift 3 | // token 4 | // 5 | // Created by James Chen on 2018/03/19. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class RandomIV { 12 | let data: Data 13 | var value: String { 14 | return data.tk_toHexString() 15 | } 16 | 17 | init() { 18 | data = Data.tk_random(of: 16) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/Storage/InMemoryStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InMemoryStorage.swift 3 | // token 4 | // 5 | // Created by James Chen on 2017/01/19. 6 | // Copyright © 2017 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// InMemoryStorage for keystores. 12 | /// - Note: In Memory Storage doesn't persist keystores thus 13 | /// should not be used in production. 14 | /// Expect to use it only for test purpose. 15 | public final class InMemoryStorage: Storage { 16 | public init() {} 17 | 18 | public func tryLoadIdentity() -> Identity? { 19 | guard 20 | let content = InMemoryStorage.db["identity.json"], 21 | let json = try? content.tk_toJSON(), 22 | let identity = Identity(json: json) 23 | else { 24 | return nil 25 | } 26 | return identity 27 | } 28 | 29 | public func loadWalletByIDs(_ walletIDs: [String]) -> [BasicWallet] { 30 | var wallets = [BasicWallet]() 31 | walletIDs.forEach { walletID in 32 | if let content = InMemoryStorage.db[walletID], 33 | let json = try? content.tk_toJSON(), 34 | let wallet = try? BasicWallet(json: json) { 35 | wallets.append(wallet) 36 | } 37 | } 38 | return wallets 39 | } 40 | 41 | public func deleteWalletByID(_ walletID: String) -> Bool { 42 | return InMemoryStorage.db.removeValue(forKey: walletID) != nil 43 | } 44 | 45 | public func cleanStorage() -> Bool { 46 | InMemoryStorage.db.removeAll() 47 | return true 48 | } 49 | 50 | public func flushIdentity(_ keystore: IdentityKeystore) -> Bool { 51 | let content = keystore.dump() 52 | InMemoryStorage.db["identity.json"] = content 53 | return true 54 | } 55 | 56 | public func flushWallet(_ keystore: Keystore) -> Bool { 57 | let content = keystore.dump() 58 | InMemoryStorage.db[keystore.id] = content 59 | return true 60 | } 61 | 62 | private static var db = [String: String]() 63 | static var enabled = true 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Storage/Storage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Storage.swift 3 | // token 4 | // 5 | // Created by James Chen on 2017/01/19. 6 | // Copyright © 2017 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Storage { 12 | init() 13 | func tryLoadIdentity() -> Identity? 14 | func loadWalletByIDs(_ walletIDs: [String]) -> [BasicWallet] 15 | func deleteWalletByID(_ walletID: String) -> Bool 16 | func cleanStorage() -> Bool 17 | func flushIdentity(_ keystore: IdentityKeystore) -> Bool 18 | func flushWallet(_ keystore: Keystore) -> Bool 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Storage/StorageManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StorageManager.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/8. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct StorageManager { 12 | public static var storageType: Storage.Type = LocalFileStorage.self { 13 | didSet { 14 | storage = storageType.init() 15 | } 16 | } 17 | public static var storage: Storage = StorageManager.storageType.init() 18 | } 19 | -------------------------------------------------------------------------------- /Sources/TokenCore.h: -------------------------------------------------------------------------------- 1 | // 2 | // TokenCore.h 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/03/26. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | FOUNDATION_EXPORT double TokenCoreVersionNumber; 12 | 13 | FOUNDATION_EXPORT const unsigned char TokenCoreVersionString[]; 14 | -------------------------------------------------------------------------------- /Sources/Utils/Data+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Data+Extension.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/05. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CryptoSwift 11 | 12 | extension Data { 13 | public func tk_toHexString() -> String { 14 | return toHexString() // From CryptoSwift 15 | } 16 | 17 | func tk_hexToBitArray() -> [UInt] { 18 | var bits = [UInt]() 19 | let hex = tk_toHexString() 20 | 21 | for char in hex { 22 | let bin = Data.tk_hexCharToBinary(char: char) 23 | for bit in bin { 24 | //let c = String(format: "%C", String(bit)) 25 | bits.append(UInt(String(bit))!) 26 | } 27 | } 28 | 29 | return bits 30 | } 31 | 32 | public static func tk_random(of length: Int) -> Data { 33 | var data = Data(count: length) 34 | data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in 35 | _ = SecRandomCopyBytes(kSecRandomDefault, length, bytes) 36 | } 37 | return data 38 | } 39 | 40 | /// Convert hex character to binary, if input is not a valid hex character, return "0000". 41 | static func tk_hexCharToBinary(char: Character) -> String { 42 | if let value = Int(String(char), radix: 16) { 43 | var bin = String(value, radix: 2) 44 | while bin.count < 4 { 45 | bin = "0" + bin 46 | } 47 | return bin 48 | } else { 49 | return "0000" 50 | } 51 | } 52 | 53 | func tk_bigEndian() -> Data { 54 | if CFByteOrderGetCurrent() == Int(CFByteOrderBigEndian.rawValue) { 55 | return self 56 | } 57 | return Data(bytes: Array(self.bytes.reversed())) 58 | } 59 | 60 | func tk_keccak256() -> String { 61 | return Encryptor.Keccak256().encrypt(data: self) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/Utils/String+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Extension.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/05. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension String { 12 | var tk_isDigits: Bool { 13 | let regex = "^[0-9]+$" 14 | let predicate = NSPredicate(format: "SELF MATCHES %@", regex) 15 | return predicate.evaluate(with: self) 16 | } 17 | 18 | func tk_substring(from: Int) -> String { 19 | return String(dropFirst(from)) 20 | } 21 | 22 | func tk_substring(to: Int) -> String { 23 | return String(dropLast(count - to)) 24 | } 25 | 26 | func lpad(width: Int, with: String) -> String { 27 | let len = lengthOfBytes(using: .utf8) 28 | 29 | if len >= width { 30 | return self 31 | } else { 32 | return "".padding(toLength: (width - len), withPad: with, startingAt: 0) + self 33 | } 34 | } 35 | 36 | func keccak256() -> String { 37 | return Encryptor.Keccak256().encrypt(data: data(using: .utf8)!) 38 | } 39 | 40 | func add0xIfNeeded() -> String { 41 | return Hex.addPrefix(self) 42 | } 43 | 44 | func removePrefix0xIfNeeded() -> String { 45 | return Hex.removePrefix(self) 46 | } 47 | 48 | public func tk_tidyMnemonic() -> String { 49 | return self.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) 50 | .trimmingCharacters(in: .whitespaces) 51 | } 52 | 53 | func tk_toJSON() throws -> JSONObject { 54 | let jsonObject: JSONObject 55 | do { 56 | let data = self.data(using: .utf8)! 57 | jsonObject = try JSONSerialization.jsonObject(with: data) as! JSONObject 58 | } catch { 59 | throw KeystoreError.invalid 60 | } 61 | return jsonObject 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/Validator/AddressValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressValidator.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/12/28. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class AddressValidator: Validator { 12 | public typealias Result = String 13 | private let address: String 14 | private let formatRegex = "^(0x)?[0-9a-f]{40}$" 15 | 16 | public init(address: String) { 17 | self.address = address 18 | } 19 | 20 | var isFormatValid: Bool { 21 | let predicate = NSPredicate(format: "SELF MATCHES[c] %@", formatRegex) 22 | return predicate.evaluate(with: address) 23 | } 24 | 25 | var isChecksumValid: Bool { 26 | let address = Hex.removePrefix(self.address.lowercased()) 27 | let hash = Encryptor.Keccak256().encrypt(hex: address.tk_toHexString()) 28 | 29 | let checksumed = address.enumerated().map { (index, char) in 30 | let hashedValue = hash.tk_substring(from: index).tk_substring(to: 1) 31 | if Int(hashedValue, radix: 16)! >= 8 { 32 | return String(char).uppercased() 33 | } else { 34 | return String(char) 35 | } 36 | }.joined() 37 | 38 | return Hex.addPrefix(checksumed) == self.address 39 | } 40 | 41 | public var isValid: Bool { 42 | if !isFormatValid { 43 | return false 44 | } 45 | 46 | return sameCase || isChecksumValid 47 | } 48 | 49 | public func validate() throws -> Result { 50 | if !isValid { 51 | throw AddressError.invalid 52 | } 53 | return address 54 | } 55 | 56 | private var sameCase: Bool { 57 | let val = Hex.removePrefix(address) 58 | return val == val.lowercased() || val == val.uppercased() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/Validator/EOSAccountNameValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSAccountNameValidator.swift 3 | // TokenCore 4 | // 5 | // Created by James Chen on 2018/07/04. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct EOSAccountNameValidator: Validator { 12 | typealias Result = String 13 | private let formatRegex = "^[1-5a-z.]{1,12}$" 14 | 15 | private let accountName: String 16 | 17 | init(_ accountName: String) { 18 | self.accountName = accountName 19 | } 20 | 21 | var isValid: Bool { 22 | if accountName.isEmpty { 23 | return true 24 | } 25 | 26 | let predicate = NSPredicate(format: "SELF MATCHES %@", formatRegex) 27 | return predicate.evaluate(with: accountName) 28 | } 29 | 30 | func validate() throws -> Result { 31 | if isValid { 32 | return accountName 33 | } 34 | 35 | throw EOSError.accountNameInvalid 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/Validator/IdentityValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IdentityValidator.swift 3 | // token 4 | // 5 | // Created by xyz on 2018/1/6. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct IdentityValidator: Validator { 12 | public typealias Result = Identity 13 | // some wallet api doesn't have identifier 14 | private let identifier: String? 15 | 16 | public init(_ identifier: String? = nil) { 17 | self.identifier = identifier 18 | } 19 | 20 | public var isValid: Bool { 21 | guard let identity = Identity.currentIdentity else { 22 | return false 23 | } 24 | if identifier != nil { 25 | return identity.identifier == identifier 26 | } 27 | return true 28 | } 29 | 30 | public func validate() throws -> Result { 31 | guard let identity = Identity.currentIdentity else { 32 | throw IdentityError.invalidIdentity 33 | } 34 | if identifier != nil && identity.identifier != identifier { 35 | throw IdentityError.invalidIdentity 36 | } 37 | return identity 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Validator/MnemonicValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MnemonicValidator.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/08. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreBitcoin 11 | 12 | public class MnemonicValidator: Validator { 13 | public typealias Result = String 14 | private let validLengths = [12, 15, 18, 21, 24] // https://dcpos.github.io/bip39/ 15 | private let mnemonic: Mnemonic 16 | 17 | public init(_ mnemonic: Mnemonic) { 18 | self.mnemonic = mnemonic 19 | } 20 | 21 | public init(_ map: [AnyHashable: Any]) throws { 22 | guard let mnemonic = map["mnemonic"] as? String else { 23 | throw GenericError.paramError 24 | } 25 | self.mnemonic = mnemonic.tk_tidyMnemonic() 26 | } 27 | 28 | private var words: [String] { 29 | return mnemonic.replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression) 30 | .trimmingCharacters(in: .whitespaces) 31 | .components(separatedBy: " ") 32 | } 33 | 34 | var isLengthValid: Bool { 35 | return validLengths.contains(words.count) 36 | } 37 | 38 | var isWordListValid: Bool { 39 | return !words.contains(where: { word -> Bool in 40 | !MnemonicDictionary.dictionary.contains(word) 41 | }) 42 | } 43 | 44 | var isChecksumValid: Bool { 45 | let btcMnemonic = BTCMnemonic(words: words, password: "", wordListType: BTCMnemonicWordListType.english) 46 | return btcMnemonic != nil 47 | } 48 | 49 | public var isValid: Bool { 50 | return isLengthValid && isWordListValid && isChecksumValid 51 | } 52 | 53 | public func validate() throws -> Result { 54 | if !isLengthValid { 55 | throw MnemonicError.lengthInvalid 56 | } 57 | 58 | if !isWordListValid { 59 | throw MnemonicError.wordInvalid 60 | } 61 | 62 | if !isChecksumValid { 63 | throw MnemonicError.checksumInvalid 64 | } 65 | 66 | return mnemonic 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Sources/Validator/PasswordValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasswordValidator.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/12/21. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class PasswordValidator: Validator { 12 | public typealias Result = String 13 | private let password: String 14 | private let formatRegex = "^.{8,}$" 15 | 16 | public init(_ password: String) { 17 | self.password = password 18 | } 19 | 20 | public init(_ map: [AnyHashable: Any]) throws { 21 | guard let password = map["password"] as? String else { 22 | throw GenericError.paramError 23 | } 24 | self.password = password 25 | } 26 | 27 | private var isEmpty: Bool { 28 | return password.isEmpty 29 | } 30 | 31 | var isFormatValid: Bool { 32 | let predicate = NSPredicate(format: "SELF MATCHES %@", formatRegex) 33 | return predicate.evaluate(with: password) 34 | } 35 | 36 | public var isValid: Bool { 37 | return !isEmpty && isFormatValid 38 | } 39 | 40 | public func validate() throws -> Result { 41 | if isEmpty { 42 | throw PasswordError.blank 43 | } 44 | 45 | if !isFormatValid { 46 | throw PasswordError.weak 47 | } 48 | 49 | return password 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Validator/V3KeystoreValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeystoreValidator.swift 3 | // token 4 | // 5 | // Created by xyz on 2017/12/30. 6 | // Copyright © 2017 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct V3KeystoreValidator: Validator { 12 | public typealias Result = JSONObject 13 | private let keystore: JSONObject 14 | public init(_ keystore: JSONObject) { 15 | self.keystore = keystore 16 | } 17 | 18 | public var isValid: Bool { 19 | guard 20 | (keystore["crypto"] as? JSONObject) != nil || (keystore["Crypto"] as? JSONObject) != nil, 21 | (keystore["version"] as? Int) == 3, 22 | let address = keystore["address"] as? String, address != "" 23 | else { 24 | return false 25 | } 26 | return true 27 | } 28 | 29 | public func validate() throws -> Result { 30 | if !isValid { 31 | throw KeystoreError.invalid 32 | } 33 | return keystore 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Validator/Validator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Validator.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/12/21. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol Validator { 12 | associatedtype Result 13 | 14 | var isValid: Bool { get } 15 | func validate() throws -> Result 16 | } 17 | -------------------------------------------------------------------------------- /Sources/Validator/WalletIDValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WalletIDValidator.swift 3 | // TokenCoreTests 4 | // 5 | // Created by James Chen on 2018/05/24. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class WalletIDValidator: Validator { 12 | typealias Result = WalletID 13 | private let walletID: WalletID 14 | private let formatRegex = "^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$" 15 | 16 | public init(walletID: WalletID) { 17 | self.walletID = walletID 18 | } 19 | 20 | /// A valid ID is lower case UUID. 21 | public var isValid: Bool { 22 | let predicate = NSPredicate(format: "SELF MATCHES %@", formatRegex) 23 | return predicate.evaluate(with: walletID) 24 | } 25 | 26 | func validate() throws -> WalletID { 27 | if !isValid { 28 | throw GenericError.paramError 29 | } 30 | return walletID 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/Encryptor/HashTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HashTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/03/06. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class HashTests: XCTestCase { 13 | func testHmacSHA256() { 14 | let key = "secret".data(using: .utf8)! 15 | let data = "hello world".data(using: .utf8)! 16 | let hash = Encryptor.Hash.hmacSHA256(key: key, data: data).tk_toHexString() 17 | XCTAssertEqual("734cc62f32841568f45715aeb9f4d7891324e6d948e4c6c60c0621cdac48623a", hash) 18 | } 19 | 20 | func testMerkleRoot() { 21 | 22 | let cases = [ 23 | ["1000", "3fa2b684fa9d80f04b70187e6c9ff1c8dd422ce1846beb79cf5e1546c7062d41"], 24 | ["2000", "4b19aa611413ba9a6b89a2be7833bb835349b9e9e9872c5eacfc82daa2e5f08f"], 25 | ["3000", "c9ec2ec071ed70d02802decd912a1e8d124420556789384efaab80fcb7ce7ecb"], 26 | ["4000", "5cfa6745c50787e3d97a1322789713036f8cab7ba534d2a996bea015d811640c"], 27 | ["5000", "233bc40f24c071507474a9c978f0f0099d0c457f9874326640be55a8a8b96325"], 28 | ["1024", "5a6c9dcbec66882a3de754eb13e61d8908e6c0b67a23c9d524224ecd93746290"], 29 | ["2048", "5ee830087937da00520c4ce3793c5c7b951d37771d69a098415ddf7d682a39d9"], 30 | ] 31 | cases.forEach { testCase in 32 | let dataLength = Int(testCase[0])! 33 | let bytes = (0.. 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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tests/Keystore/Bitcoin/BTCKeystoreTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BTCKeystoreTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/24. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class BTCKeystoreTests: TestCase { 13 | func testImportWithPrivateKey() { 14 | let meta = WalletMeta(chain: .btc, source: .wif, network: .mainnet) 15 | let keystore = try? BTCKeystore(password: TestData.password, wif: TestData.wif, metadata: meta) 16 | XCTAssertNotNil(keystore) 17 | XCTAssertEqual("1N3RC53vbaDNrziTdWmctBEeQ4fo4quNpq", keystore?.address) 18 | } 19 | 20 | func testImportWithPrivateKeyTestnet() { 21 | let meta = WalletMeta(chain: .btc, source: .wif, network: .testnet) 22 | let keystore = try? BTCKeystore(password: TestData.password, wif: TestData.wifTestnet, metadata: meta) 23 | XCTAssertNotNil(keystore) 24 | XCTAssertEqual("mgpHw67hvPxe8qQbtVZ8a7kHzn8U2v3ihF", keystore?.address) 25 | } 26 | 27 | func testImportFailureWithInvaidPrivateKey() { 28 | let meta = WalletMeta(chain: .btc, source: .wif) 29 | XCTAssertThrowsError(try BTCKeystore(password: TestData.password, wif: TestData.privateKey, metadata: meta)) 30 | } 31 | 32 | func testInitWithJSON() { 33 | let data = TestHelper.loadJSON(filename: "v3-wif").data(using: .utf8)! 34 | let json = try! JSONSerialization.jsonObject(with: data) as! JSONObject 35 | let keystore = try? BTCKeystore(json: json) 36 | XCTAssertNotNil(keystore) 37 | XCTAssertEqual(keystore!.meta.source, WalletMeta.Source.wif) 38 | } 39 | } 40 | 41 | // SegWit 42 | extension BTCKeystoreTests { 43 | func testImportWithPrivateKeySegWit() { 44 | var meta = WalletMeta(chain: .btc, source: .wif, network: .testnet) 45 | meta.segWit = .p2wpkh 46 | let keystore = try? BTCKeystore(password: TestData.password, wif: TestData.wifTestnet, metadata: meta) 47 | XCTAssertNotNil(keystore) 48 | XCTAssertEqual("2NB53xvb7eociGEYThz5WZWvr4qZexH8LG7", keystore?.address) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Tests/Keystore/CryptoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoTests.swift 3 | // tokenTests 4 | // 5 | // Created by Kai Chen on 22/09/2017. 6 | // Copyright © 2017 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class CryptoTests: TestCase { 13 | func testCreate() { 14 | let crypto = Crypto(password: TestData.password, privateKey: TestData.privateKey) 15 | XCTAssertEqual(TestData.privateKey, crypto.privateKey(password: TestData.password)) 16 | XCTAssertEqual(crypto.mac, crypto.macFrom(password: TestData.password)) 17 | } 18 | 19 | func testToJSON() { 20 | let crypto = Crypto(password: TestData.password, privateKey: TestData.privateKey) 21 | let json = crypto.toJSON() 22 | XCTAssertEqual(json["cipher"] as! String, "aes-128-ctr") 23 | XCTAssertEqual(json["kdf"] as! String, "scrypt") 24 | XCTAssertEqual(json["mac"] as! String, crypto.macFrom(password: TestData.password)) 25 | } 26 | 27 | func testInitWithJSON() { 28 | let data = TestHelper.loadJSON(filename: "v3-crypto-scrypt-1024").data(using: .utf8)! 29 | let json = try! JSONSerialization.jsonObject(with: data) as! JSONObject 30 | let crypto = try! Crypto(json: json) 31 | XCTAssertEqual(json["mac"] as! String, crypto.macFrom(password: TestData.password)) 32 | XCTAssertEqual(TestData.privateKey, crypto.privateKey(password: TestData.password)) 33 | } 34 | 35 | func testInitWithInvalidJSON() { 36 | let json = ["bad": "json"] 37 | XCTAssertThrowsError(try Crypto(json: json)) 38 | } 39 | } 40 | 41 | // Cache 42 | extension CryptoTests { 43 | func testCacheDerivedKey() { 44 | let crypto = Crypto(password: TestData.password, privateKey: TestData.privateKey, cacheDerivedKey: true) 45 | let cached = crypto.cachedDerivedKey(with: TestData.password) 46 | XCTAssertEqual(cached, crypto.cachedDerivedKey(with: TestData.password)) 47 | XCTAssertNotEqual(cached, crypto.cachedDerivedKey(with: TestData.wrongPassword)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Keystore/Ethereum/ETHMnemonicKeystoreTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ETHMnemonicKeystoreTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/24. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class ETHMnemonicKeystoreTests: TestCase { 13 | func testInit() { 14 | let meta = WalletMeta(chain: .eth, source: .mnemonic) 15 | let keystore = try? ETHMnemonicKeystore(password: TestData.password, mnemonic: TestData.mnemonic, path: BIP44.eth, metadata: meta) 16 | XCTAssertNotNil(keystore) 17 | XCTAssertEqual(keystore!.address, "6031564e7b2f5cc33737807b2e58daff870b590b") 18 | XCTAssertEqual(keystore!.mnemonicPath, BIP44.eth) 19 | } 20 | 21 | func testInitWithJSON() { 22 | let meta = WalletMeta(chain: .eth, source: .mnemonic) 23 | let keystore = try! ETHMnemonicKeystore(password: TestData.password, mnemonic: TestData.mnemonic, path: BIP44.eth, metadata: meta) 24 | let new = try? ETHMnemonicKeystore(json: keystore.toJSON()) 25 | XCTAssertNotNil(new) 26 | XCTAssertEqual(new!.address, "6031564e7b2f5cc33737807b2e58daff870b590b") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tests/Keystore/Identity/IdentityKeystoreTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IdentityKeystoreTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/24. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class IdentityKeystoreTests: TestCase { 13 | func testInit() { 14 | let meta = WalletMeta(source: .newIdentity) 15 | let keystore = try? IdentityKeystore(metadata: meta, mnemonic: TestData.mnemonic, password: TestData.password) 16 | XCTAssertNotNil(keystore) 17 | } 18 | 19 | func testInitFailureWithInvalidMnemomic() { 20 | let meta = WalletMeta(source: .newIdentity) 21 | XCTAssertThrowsError(try IdentityKeystore(metadata: meta, mnemonic: "a bad phrase", password: TestData.password)) 22 | } 23 | 24 | func testVerify() { 25 | let meta = WalletMeta(source: .newIdentity) 26 | let keystore = try! IdentityKeystore(metadata: meta, mnemonic: TestData.mnemonic, password: TestData.password) 27 | XCTAssert(keystore.verify(password: TestData.password)) 28 | XCTAssertFalse(keystore.verify(password: "bad" + TestData.password)) 29 | } 30 | 31 | func testMnemonicFromPassword() { 32 | let meta = WalletMeta(source: .newIdentity) 33 | let keystore = try! IdentityKeystore(metadata: meta, mnemonic: TestData.mnemonic, password: TestData.password) 34 | let mnemomic = try? keystore.mnemonic(from: TestData.password) 35 | XCTAssertEqual(mnemomic, TestData.mnemonic) 36 | } 37 | 38 | func testSerializeToMap() { 39 | let meta = WalletMeta(source: .newIdentity) 40 | var keystore = try! IdentityKeystore(metadata: meta, mnemonic: TestData.mnemonic, password: TestData.password) 41 | 42 | let data = TestHelper.loadJSON(filename: "v3-pbkdf2-testpassword").data(using: .utf8)! 43 | let json = try! JSONSerialization.jsonObject(with: data) as! JSONObject 44 | let ethKeystore = try! ETHKeystore(json: json) 45 | let wallet = BasicWallet(ethKeystore) 46 | keystore.wallets.append(wallet) 47 | 48 | let map = keystore.serializeToMap() 49 | XCTAssertEqual((map["wallets"] as! [[String: Any]]).first!["address"] as! String, "008aeeda4d805471df9b2a5b0f38a0c3bcba786b") 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/Keystore/KeystoreTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeystoreTests.swift 3 | // TokenCoreTests 4 | // 5 | // Created by James Chen on 2018/05/21. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class KeystoreTests: TestCase { 13 | func testEthSerializeToMap() { 14 | let meta = WalletMeta(chain: .eth, source: .privateKey) 15 | let keystore = try! ETHKeystore(password: TestData.password, privateKey: TestData.privateKey, metadata: meta) 16 | XCTAssertNotNil(keystore) 17 | } 18 | 19 | func testBtcSerializeToMap() { 20 | var meta = WalletMeta(chain: .btc, source: .wif) 21 | meta.segWit = .p2wpkh 22 | let keystore = try! BTCKeystore(password: TestData.password, wif: TestData.wif, metadata: meta) 23 | XCTAssertNotNil(keystore) 24 | XCTAssertEqual(SegWit.p2wpkh.rawValue, keystore.serializeToMap()["segWit"] as! String) 25 | } 26 | 27 | func testGenerateKeystoreId() { 28 | XCTAssertNotNil(BTCMnemonicKeystore.generateKeystoreId()) 29 | XCTAssertNotEqual(BTCMnemonicKeystore.generateKeystoreId(), BTCMnemonicKeystore.generateKeystoreId()) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/Keystore/WalletMetaTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WalletMetaTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/24. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class WalletMetaTests: XCTestCase { 13 | func testCreate() { 14 | let meta = WalletMeta(chain: .btc, source: .privateKey) 15 | XCTAssertEqual(meta.chain, ChainType.btc) 16 | XCTAssertEqual(meta.source, WalletMeta.Source.privateKey) 17 | XCTAssertEqual(meta.network, Network.mainnet) 18 | } 19 | 20 | func testIsMainnet() { 21 | XCTAssert(WalletMeta(source: .privateKey).isMainnet) 22 | XCTAssertFalse(WalletMeta(chain: .btc, source: .privateKey, network: .testnet).isMainnet) 23 | } 24 | 25 | func testMerge() { 26 | var meta = WalletMeta(chain: .btc, source: .privateKey) 27 | meta.name = "First wallet" 28 | let new = meta.mergeMeta("Second wallet", chainType: .eth) 29 | XCTAssertEqual(new.name, "Second wallet") 30 | XCTAssertEqual(new.chain, ChainType.eth) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/Storage/StorageManagerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StorageManagerTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/03/12. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class StorageManagerTests: XCTestCase { 13 | func testInMemoryStorage() { 14 | StorageManager.storageType = InMemoryStorage.self 15 | XCTAssert(StorageManager.storage is InMemoryStorage) 16 | } 17 | 18 | func testLocalFileStorage() { 19 | StorageManager.storageType = LocalFileStorage.self 20 | XCTAssert(StorageManager.storage is LocalFileStorage) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tests/TestHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHelper.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/09/26. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TestHelper { 12 | static func loadJSON(filename: String) -> String { 13 | let jsonPath = Bundle(for: TestHelper.self).path(forResource: filename, ofType: "json")! 14 | return try! String(contentsOfFile: jsonPath) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Tests/Utils/DataExtensionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataExtensionTests.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/31. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class DataExtensionTests: XCTestCase { 13 | func testHexCharToBinary() { 14 | let mapping: [Character: String] = [ 15 | "0": "0000", 16 | "1": "0001", 17 | "2": "0010", 18 | "3": "0011", 19 | "4": "0100", 20 | "5": "0101", 21 | "6": "0110", 22 | "7": "0111", 23 | "8": "1000", 24 | "9": "1001", 25 | "a": "1010", 26 | "A": "1010", 27 | "b": "1011", 28 | "B": "1011", 29 | "c": "1100", 30 | "C": "1100", 31 | "d": "1101", 32 | "D": "1101", 33 | "e": "1110", 34 | "E": "1110", 35 | "f": "1111", 36 | "F": "1111", 37 | "g": "0000" 38 | ] 39 | for (hex, bin) in mapping { 40 | XCTAssertEqual(bin, Data.tk_hexCharToBinary(char: hex)) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/Utils/RLPTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ETHRlpTests.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/27. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class RLPTests: XCTestCase { 13 | func testZero() { 14 | XCTAssertEqual("80", RLP.encode(0)) 15 | } 16 | 17 | func testString() { 18 | XCTAssertEqual( 19 | "b839303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030", 20 | RLP.encode("000000000000000000000000000000000000000000000000000000000") 21 | ) 22 | } 23 | 24 | func testBinary() { 25 | XCTAssertEqual( 26 | "9d0000000000000000000000000001000000000000000000000000000000", 27 | RLP.encode(String(bytes: Hex.toBytes("0000000000000000000000000001000000000000000000000000000000"), encoding: .ascii)!) 28 | ) 29 | } 30 | 31 | func testJSONFixture() { 32 | let json = TestHelper.loadJSON(filename: "rlp") // https://github.com/ethereumjs/tests/blob/58cd17e70b2a7da28dd77cf56a9f5e6cd672ec99/RLPTests/rlptest.json 33 | let data = json.data(using: .utf8)! 34 | let jsonObject = try! JSONSerialization.jsonObject(with: data) as! [String: Any] 35 | for (_, testPair) in jsonObject { 36 | let inOut = testPair as! [String: Any] 37 | let input = inOut["in"]! 38 | let output = (inOut["out"] as! String).uppercased() 39 | let encoded: String = RLP.encode(input).uppercased() 40 | XCTAssertEqual(output, encoded, "Encoding \(input)") 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/Utils/StringExtensionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringExtensionTests.swift 3 | // token 4 | // 5 | // Created by James Chen on 2016/10/25. 6 | // Copyright © 2016 imToken PTE. LTD. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class StringExtensionTests: XCTestCase { 13 | func testIsDigits() { 14 | XCTAssert("156".tk_isDigits) 15 | XCTAssertFalse("0x156".tk_isDigits) 16 | } 17 | 18 | func testSutstring() { 19 | let str = "Hello, string" 20 | XCTAssertEqual(str.tk_substring(to: 5), "Hello") 21 | XCTAssertEqual(str.tk_substring(from: 7), "string") 22 | } 23 | 24 | func testAdd0xIfNeeded() { 25 | XCTAssertEqual("1234".add0xIfNeeded(), "0x1234") 26 | } 27 | 28 | func testRemovePrefix0xIfNeeded() { 29 | XCTAssertEqual("0x1234".removePrefix0xIfNeeded(), "1234") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/Validator/AddressValidatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddressValidatorTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/16. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class AddressValidatorTests: TestCase { 13 | func testValidate() { 14 | let address = "0xF308646bd9e6808ca7BE41E3e580f8E7196C5573" 15 | let validator = AddressValidator(address: address) 16 | XCTAssert(validator.isChecksumValid) 17 | XCTAssert(validator.isFormatValid) 18 | XCTAssert(validator.isValid) 19 | XCTAssertNoThrow(try validator.validate()) 20 | } 21 | 22 | func testValidateReturn() { 23 | let address = "0xF308646bd9e6808ca7BE41E3e580f8E7196C5573" 24 | let validator = AddressValidator(address: address) 25 | do { 26 | let result = try validator.validate() 27 | XCTAssertEqual(address, result) 28 | } catch { 29 | XCTFail("No throw!") 30 | } 31 | } 32 | 33 | func testInvalidLength() { 34 | let address = "0xF308646bd9e6808ca7BE41E3e580f8E7196C5573-badlength" 35 | let validator = AddressValidator(address: address) 36 | XCTAssertFalse(validator.isFormatValid) 37 | XCTAssertFalse(validator.isValid) 38 | XCTAssertThrowsError(try validator.validate()) 39 | } 40 | 41 | func testInvalidCharacter() { 42 | let address = "0xF308646bd9e6808ca7BE41E3e580f8E7196C557G" 43 | let validator = AddressValidator(address: address) 44 | XCTAssertFalse(validator.isFormatValid) 45 | XCTAssertFalse(validator.isValid) 46 | XCTAssertThrowsError(try validator.validate()) 47 | } 48 | 49 | func testInvalidChecksum() { 50 | let address = "0xf308646bd9e6808ca7BE41E3e580f8E7196C5573" 51 | let validator = AddressValidator(address: address) 52 | XCTAssertFalse(validator.isChecksumValid) 53 | XCTAssertFalse(validator.isValid) 54 | XCTAssertThrowsError(try validator.validate()) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Tests/Validator/EOSAccountNameValidatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EOSAccountNameValidatorTests.swift 3 | // TokenCoreTests 4 | // 5 | // Created by James Chen on 2018/07/04. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class EOSAccountNameValidatorTests: XCTestCase { 13 | func testValidNames() { 14 | let accountNames = [ 15 | "", 16 | "hello", 17 | "name1", 18 | "name12", 19 | "name12", 20 | "name123", 21 | "name1234", 22 | "name1245", 23 | "sub.one" 24 | ] 25 | accountNames.forEach { accountName in 26 | XCTAssert(EOSAccountNameValidator(accountName).isValid) 27 | } 28 | } 29 | 30 | func testInvalidNames() { 31 | let accountNames = [ 32 | "1111111111111", 33 | "@", 34 | "#", 35 | "hello6", 36 | "hello7", 37 | "hello8", 38 | "hello9", 39 | "hello0", 40 | "Name" 41 | ] 42 | accountNames.forEach { accountName in 43 | XCTAssertFalse(EOSAccountNameValidator(accountName).isValid) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/Validator/IdentityValidatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IdentityValidatorTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/16. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class IdentityValidatorTests: TestCase { 13 | func testValidate() { 14 | let validator = IdentityValidator() 15 | XCTAssert(validator.isValid) 16 | XCTAssertNoThrow(try validator.validate()) 17 | } 18 | 19 | func testValidateReturn() { 20 | let validator = IdentityValidator() 21 | do { 22 | let result = try validator.validate() 23 | XCTAssertEqual(result.identifier, Identity.currentIdentity!.identifier) 24 | } catch { 25 | XCTFail("No throw!") 26 | } 27 | } 28 | 29 | func testInvalidIdentifier() { 30 | let validator = IdentityValidator(Identity.currentIdentity!.identifier + "-copy") 31 | XCTAssertFalse(validator.isValid) 32 | XCTAssertThrowsError(try validator.validate()) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Tests/Validator/MnemonicValidatorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MnemonicValidatorTests.swift 3 | // tokenTests 4 | // 5 | // Created by James Chen on 2018/02/16. 6 | // Copyright © 2018 ConsenLabs. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TokenCore 11 | 12 | class MnemonicValidatorTests: TestCase { 13 | func testValidate() { 14 | let validator = MnemonicValidator(TestData.mnemonic) 15 | XCTAssert(validator.isLengthValid) 16 | XCTAssert(validator.isWordListValid) 17 | XCTAssert(validator.isChecksumValid) 18 | XCTAssert(validator.isValid) 19 | XCTAssertNoThrow(try validator.validate()) 20 | } 21 | 22 | func testValidateMap() { 23 | let validator = try! MnemonicValidator(["mnemonic": TestData.mnemonic]) 24 | XCTAssert(validator.isLengthValid) 25 | XCTAssert(validator.isWordListValid) 26 | XCTAssert(validator.isChecksumValid) 27 | XCTAssert(validator.isValid) 28 | XCTAssertNoThrow(try validator.validate()) 29 | } 30 | 31 | func testInvalidMap() { 32 | do { 33 | _ = try MnemonicValidator(["abc": "abc"]) 34 | XCTFail() 35 | } catch let err { 36 | XCTAssertEqual(GenericError.paramError.localizedDescription, err.localizedDescription) 37 | } 38 | } 39 | 40 | func testValidateReturn() { 41 | let validator = MnemonicValidator(TestData.mnemonic) 42 | do { 43 | let result = try validator.validate() 44 | XCTAssertEqual(TestData.mnemonic, result) 45 | } catch { 46 | XCTFail("No throw!") 47 | } 48 | } 49 | 50 | func testInvalidLength() { 51 | (1...30).forEach { length in 52 | if ![12, 15, 18, 21, 24].contains(length) { 53 | let input = (0.. "james@ashchan.com" } 17 | s.platform = :ios, "9.0" 18 | 19 | s.source = { :git => "https://github.com/consenlabs/ios-token-core.git", :tag => "#{s.version}" } 20 | s.source_files = "Sources/**/*.{h,m,swift}" 21 | s.swift_version = "4.0" 22 | s.dependency "CryptoSwift", "0.9.0" 23 | s.dependency "BigInt", "3.0.0" 24 | s.dependency "GRKOpenSSLFramework" 25 | s.dependency "CoreBitcoin" 26 | s.dependency "secp256k1.swift" 27 | end 28 | -------------------------------------------------------------------------------- /TokenCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TokenCore.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TokenCore.xcodeproj/xcshareddata/xcschemes/TokenCoreTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /TokenCore.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TokenCore.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAddressSubclass.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #ifndef CoreBitcoin_BTCAddressSubclass_h 4 | #define CoreBitcoin_BTCAddressSubclass_h 5 | 6 | @interface BTCAddress () 7 | @property(nonatomic, readwrite) NSData* data; 8 | @end 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetAddress.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCAddress.h" 4 | 5 | @interface BTCAssetAddress : BTCAddress 6 | @property(nonatomic, readonly, nonnull) BTCAddress* bitcoinAddress; 7 | + (nonnull instancetype) addressWithBitcoinAddress:(nonnull BTCAddress*)btcAddress; 8 | @end 9 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetAddress.m: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCAssetAddress.h" 4 | #import "BTCData.h" 5 | #import "BTCBase58.h" 6 | 7 | @interface BTCAssetAddress () 8 | @property(nonatomic, readwrite) BTCAddress* bitcoinAddress; 9 | @end 10 | 11 | // OpenAssets Address, e.g. akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy (corresponds to 16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM) 12 | @implementation BTCAssetAddress 13 | 14 | #define BTCAssetAddressNamespace 0x13 15 | 16 | + (void) load { 17 | [BTCAddress registerAddressClass:self version:BTCAssetAddressNamespace]; 18 | } 19 | 20 | + (instancetype) addressWithBitcoinAddress:(BTCAddress*)btcAddress { 21 | if (!btcAddress) return nil; 22 | BTCAssetAddress* addr = [[self alloc] init]; 23 | addr.bitcoinAddress = btcAddress; 24 | return addr; 25 | } 26 | 27 | + (instancetype) addressWithString:(NSString*)string { 28 | NSMutableData* composedData = BTCDataFromBase58Check(string); 29 | uint8_t version = ((unsigned char*)composedData.bytes)[0]; 30 | return [self addressWithComposedData:composedData cstring:[string cStringUsingEncoding:NSUTF8StringEncoding] version:version]; 31 | } 32 | 33 | + (instancetype) addressWithComposedData:(NSData*)composedData cstring:(const char*)cstring version:(uint8_t)version { 34 | if (!composedData) return nil; 35 | if (composedData.length < 2) return nil; 36 | 37 | if (version == BTCAssetAddressNamespace) { // same for testnet and mainnet 38 | BTCAddress* btcAddr = [BTCAddress addressWithString:BTCBase58CheckStringWithData([composedData subdataWithRange:NSMakeRange(1, composedData.length - 1)])]; 39 | return [self addressWithBitcoinAddress:btcAddr]; 40 | } else { 41 | return nil; 42 | } 43 | } 44 | 45 | - (NSMutableData*) dataForBase58Encoding { 46 | NSMutableData* data = [NSMutableData dataWithLength:1]; 47 | char* buf = data.mutableBytes; 48 | buf[0] = BTCAssetAddressNamespace; 49 | [data appendData:[(BTCAssetAddress* /* cast only to expose the method that is defined in BTCAddress anyway */)self.bitcoinAddress dataForBase58Encoding]]; 50 | return data; 51 | } 52 | 53 | - (unsigned char) versionByte { 54 | return BTCAssetAddressNamespace; 55 | } 56 | 57 | - (BOOL) isTestnet { 58 | return self.bitcoinAddress.isTestnet; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetID.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCAddress.h" 4 | 5 | @interface BTCAssetID : BTCAddress 6 | 7 | + (nullable instancetype) assetIDWithHash:(nullable NSData*)data; 8 | 9 | + (nullable instancetype) assetIDWithString:(nullable NSString*)string; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetID.m: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCAssetID.h" 4 | #import "BTCAddressSubclass.h" 5 | 6 | static const uint8_t BTCAssetIDVersionMainnet = 23; // "A" prefix 7 | static const uint8_t BTCAssetIDVersionTestnet = 115; 8 | 9 | @implementation BTCAssetID 10 | 11 | + (void) load { 12 | [BTCAddress registerAddressClass:self version:BTCAssetIDVersionMainnet]; 13 | [BTCAddress registerAddressClass:self version:BTCAssetIDVersionTestnet]; 14 | } 15 | 16 | #define BTCAssetIDLength 20 17 | 18 | + (instancetype) assetIDWithString:(NSString*)string { 19 | return [self addressWithString:string]; 20 | } 21 | 22 | + (instancetype) assetIDWithHash:(NSData*)data { 23 | if (!data) return nil; 24 | if (data.length != BTCAssetIDLength) { 25 | NSLog(@"+[BTCAssetID addressWithData] cannot init with hash %d bytes long", (int)data.length); 26 | return nil; 27 | } 28 | BTCAssetID* addr = [[self alloc] init]; 29 | addr.data = [NSMutableData dataWithData:data]; 30 | return addr; 31 | } 32 | 33 | + (instancetype) addressWithComposedData:(NSData*)composedData cstring:(const char*)cstring version:(uint8_t)version { 34 | if (composedData.length != (1 + BTCAssetIDLength)) { 35 | NSLog(@"BTCAssetID: cannot init with %d bytes (need 20+1 bytes)", (int)composedData.length); 36 | return nil; 37 | } 38 | BTCAssetID* addr = [[self alloc] init]; 39 | addr.data = [[NSMutableData alloc] initWithBytes:((const char*)composedData.bytes) + 1 length:composedData.length - 1]; 40 | return addr; 41 | } 42 | 43 | - (NSMutableData*) dataForBase58Encoding { 44 | NSMutableData* data = [NSMutableData dataWithLength:1 + BTCAssetIDLength]; 45 | char* buf = data.mutableBytes; 46 | buf[0] = [self versionByte]; 47 | memcpy(buf + 1, self.data.bytes, BTCAssetIDLength); 48 | return data; 49 | } 50 | 51 | - (uint8_t) versionByte { 52 | // TODO: support testnet 53 | return BTCAssetIDVersionMainnet; 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetType.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | extern NSString* __nonnull const BTCAssetTypeBitcoin; 6 | extern NSString* __nonnull const BTCAssetTypeOpenAssets; 7 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCAssetType.m: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCAssetType.h" 4 | 5 | NSString* __nonnull const BTCAssetTypeBitcoin = @"bitcoin"; 6 | NSString* __nonnull const BTCAssetTypeOpenAssets = @"openassets"; 7 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCBase58.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | // Base58 is used for compact human-friendly representation of Bitcoin addresses and private keys. 6 | // Typically Base58-encoded text also contains a checksum. 7 | // Addresses look like 19FGfswVqxNubJbh1NW8A4t51T9x9RDVWQ 8 | // Private keys look like 5KQntKuhYWSRXNqp2yhdXzjekYAR7US3MT1715Mbv5CyUKV6hVe 9 | // 10 | // Here is what Satoshi said about Base58: 11 | // Why base-58 instead of standard base-64 encoding? 12 | // - Don't want 0OIl characters that look the same in some fonts and 13 | // could be used to create visually identical looking account numbers. 14 | // - A string with non-alphanumeric characters is not as easily accepted as an account number. 15 | // - E-mail usually won't line-break if there's no punctuation to break at. 16 | // - Double-clicking selects the whole number as one word if it's all alphanumeric. 17 | 18 | 19 | // See NS+BTCBase58.h for easy to use categories. 20 | 21 | // Returns data for a Base58 string without checksum 22 | // Data is mutable so you can clear sensitive information as soon as possible. 23 | NSMutableData* BTCDataFromBase58(NSString* string); 24 | NSMutableData* BTCDataFromBase58CString(const char* cstring); 25 | 26 | // Returns data for a Base58 string with checksum 27 | NSMutableData* BTCDataFromBase58Check(NSString* string); 28 | NSMutableData* BTCDataFromBase58CheckCString(const char* cstring); 29 | 30 | // String in Base58 without checksum, you need to free it yourself. 31 | // It's mutable so you can clear it securely yourself. 32 | char* BTCBase58CStringWithData(NSData* data); 33 | 34 | // Same as above, but returns an immutable autoreleased string. Suitable for non-sensitive data. 35 | NSString* BTCBase58StringWithData(NSData* data); 36 | 37 | // String in Base58 with checksum, you need to free it yourself. 38 | // It's mutable so you can clear it securely yourself. 39 | char* BTCBase58CheckCStringWithData(NSData* data); 40 | 41 | // Same as above, but returns an immutable autoreleased string. Suitable for non-sensitive data. 42 | NSString* BTCBase58CheckStringWithData(NSData* data); 43 | 44 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCBlock.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | @class BTCBlockHeader; 6 | @interface BTCBlock : NSObject 7 | 8 | @property(nonatomic, readonly) BTCBlockHeader* header; 9 | @property(nonatomic) NSArray* transactions; 10 | 11 | @property(nonatomic, readonly) NSData* blockHash; 12 | @property(nonatomic, readonly) NSString* blockID; 13 | @property(nonatomic, readonly) NSData* data; // serialized form of the block 14 | 15 | // Informational Properties 16 | // ------------------------ 17 | // These are available via external APIs like Chain.com. 18 | 19 | // Height of the block. Default is 0. 20 | @property(nonatomic) NSInteger height; 21 | 22 | // Number of confirmations. Default is NSNotFound. 23 | @property(nonatomic) NSUInteger confirmations; 24 | 25 | // Arbitrary information attached to this instance. 26 | // The reference is copied when this instance is copied. 27 | // Default is nil. 28 | @property(nonatomic) NSDictionary* userInfo; 29 | 30 | 31 | // Computes merkle root hash from the current transaction array. 32 | - (NSData*) computeMerkleRootHash; 33 | 34 | // Updates header.merkleRootHash by hashing transactions. 35 | // Equivalent to `block.header.merkleRootHash = [block computeMerkleRootHash]`. 36 | - (void) updateMerkleTree; 37 | 38 | // Instantiates an empty block with a given header. 39 | - (id) initWithHeader:(BTCBlockHeader*)header; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCBlockHeader.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | static const int32_t BTCBlockCurrentVersion = 2; 6 | 7 | @interface BTCBlockHeader : NSObject 8 | 9 | + (NSUInteger) headerLength; 10 | 11 | @property(nonatomic) int32_t version; 12 | @property(nonatomic) NSData* previousBlockHash; 13 | @property(nonatomic) NSString* previousBlockID; 14 | @property(nonatomic) NSData* merkleRootHash; 15 | @property(nonatomic) uint32_t time; 16 | @property(nonatomic) uint32_t difficultyTarget; // aka nBits 17 | @property(nonatomic) uint32_t nonce; 18 | 19 | @property(nonatomic, readonly) NSData* blockHash; 20 | @property(nonatomic, readonly) NSString* blockID; 21 | @property(nonatomic, readonly) NSData* data; 22 | 23 | // Date and time of the block. 24 | @property(nonatomic) NSDate* date; 25 | 26 | 27 | // Informational Properties 28 | // ------------------------ 29 | // These are available via external APIs like Chain.com. 30 | 31 | // Height of the block. Default is 0. 32 | @property(nonatomic) NSInteger height; 33 | 34 | // Number of confirmations. Default is NSNotFound. 35 | @property(nonatomic) NSUInteger confirmations; 36 | 37 | // Arbitrary information attached to this instance. 38 | // The reference is copied when this instance is copied. 39 | // Default is nil. 40 | @property(nonatomic) NSDictionary* userInfo; 41 | 42 | 43 | // Parses block from data buffer 44 | - (id) initWithData:(NSData*)data; 45 | 46 | // Parses input stream 47 | - (id) initWithStream:(NSInputStream*)stream; 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCBlockchainInfo.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | // Collection of useful APIs for Blockchain.info 6 | @interface BTCBlockchainInfo : NSObject 7 | 8 | // Getting unspent outputs. 9 | 10 | // Builds a request from a list of BTCAddress objects. 11 | - (NSMutableURLRequest*) requestForUnspentOutputsWithAddresses:(NSArray*)addresses; 12 | // List of BTCTransactionOutput instances parsed from the response. 13 | - (NSArray*) unspentOutputsForResponseData:(NSData*)responseData error:(NSError**)errorOut; 14 | // Makes sync request for unspent outputs and parses the outputs. 15 | - (NSArray*) unspentOutputsWithAddresses:(NSArray*)addresses error:(NSError**)errorOut; 16 | 17 | 18 | // Broadcasting transaction 19 | 20 | // Request to broadcast a raw transaction data. 21 | - (NSMutableURLRequest*) requestForTransactionBroadcastWithData:(NSData*)data; 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCChainCom.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | @class BTCAddress; 5 | 6 | // Collection of APIs for Chain.con 7 | @interface BTCChainCom : NSObject 8 | 9 | - (id)initWithToken:(NSString *)token; // Free API Token from http://chain.com 10 | 11 | // Getting unspent outputs. 12 | 13 | // Builds a request from a list of BTCAddress objects. 14 | - (NSMutableURLRequest*) requestForUnspentOutputsWithAddress:(BTCAddress*)address; 15 | // List of BTCTransactionOutput instances parsed from the response. 16 | - (NSArray*) unspentOutputsForResponseData:(NSData*)responseData error:(NSError**)errorOut; 17 | // Makes sync request for unspent outputs and parses the outputs. 18 | - (NSArray*) unspentOutputsWithAddress:(BTCAddress*)addresses error:(NSError**)errorOut; 19 | 20 | 21 | // Broadcasting transaction 22 | 23 | // Request to broadcast a raw transaction data. 24 | - (NSMutableURLRequest*) requestForTransactionBroadcastWithData:(NSData*)data; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCEncryptedBackup.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | // Implementation of [Automatic Encrypted Wallet Backups](https://github.com/oleganza/bitcoin-papers/blob/master/AutomaticEncryptedWalletBackups.md) scheme. 4 | // For test vectors, see unit tests (BTCEncryptedBackup+Tests.m). 5 | 6 | #import 7 | 8 | typedef NS_ENUM(unsigned char, BTCEncryptedBackupVersion) { 9 | BTCEncryptedBackupVersion1 = 0x01, 10 | }; 11 | 12 | @class BTCNetwork; 13 | @class BTCKey; 14 | @interface BTCEncryptedBackup : NSObject 15 | 16 | // Default version is BTCEncryptedBackupVersion1. 17 | @property(nonatomic, readonly) BTCEncryptedBackupVersion version; 18 | 19 | // Timestamp of the backup. If not specified, during encryption set to current time. 20 | @property(nonatomic, readonly) NSTimeInterval timestamp; 21 | @property(nonatomic, readonly) NSDate* date; 22 | 23 | @property(nonatomic, readonly) NSData* decryptedData; 24 | @property(nonatomic, readonly) NSData* encryptedData; 25 | 26 | @property(nonatomic, readonly) NSString* walletID; 27 | @property(nonatomic, readonly) BTCKey* authenticationKey; 28 | 29 | + (instancetype) encrypt:(NSData*)data backupKey:(NSData*)backupKey; 30 | + (instancetype) encrypt:(NSData*)data backupKey:(NSData*)backupKey timestamp:(NSTimeInterval)timestamp; 31 | + (instancetype) decrypt:(NSData*)data backupKey:(NSData*)backupKey; 32 | 33 | + (NSData*) backupKeyForNetwork:(BTCNetwork*)network masterKey:(NSData*)masterKey; 34 | + (BTCKey*) authenticationKeyWithBackupKey:(NSData*)backupKey; 35 | + (NSString*) walletIDWithAuthenticationKey:(NSData*)authPubkey; 36 | 37 | // For testing/audit purposes only: 38 | 39 | @property(nonatomic, readonly) NSData* encryptionKey; 40 | @property(nonatomic, readonly) NSData* iv; 41 | @property(nonatomic, readonly) NSData* merkleRoot; 42 | @property(nonatomic, readonly) NSData* ciphertext; 43 | @property(nonatomic, readonly) NSData* dataForSigning; 44 | @property(nonatomic, readonly) NSData* signature; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCEncryptedMessage.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | @class BTCKey; 6 | 7 | // Implementation of [ECIES](http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme) 8 | // compatible with [Bitcore ECIES](https://github.com/bitpay/bitcore-ecies) implementation. 9 | @interface BTCEncryptedMessage : NSObject 10 | 11 | // When encrypting, sender's keypair must contain a private key. 12 | @property(nonatomic) BTCKey* senderKey; 13 | 14 | // When decrypting, recipient's keypair must contain a private key. 15 | @property(nonatomic) BTCKey* recipientKey; 16 | 17 | - (NSData*) encrypt:(NSData*)plaintext; 18 | - (NSData*) decrypt:(NSData*)ciphertext; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCErrors.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | extern NSString* const BTCErrorDomain; 6 | 7 | typedef NS_ENUM(NSUInteger, BTCErrorCode) { 8 | 9 | // Canonical pubkey/signature check errors 10 | BTCErrorNonCanonicalPublicKey = 4001, 11 | BTCErrorNonCanonicalScriptSignature = 4002, 12 | 13 | // Script verification errors 14 | BTCErrorScriptError = 5001, 15 | 16 | // BTCPriceSource errors 17 | BTCErrorUnsupportedCurrencyCode = 6001, 18 | 19 | // BIP70 Payment Protocol errors 20 | BTCErrorPaymentRequestInvalidResponse = 7001, 21 | BTCErrorPaymentRequestTooBig = 7002, 22 | 23 | // Secret Sharing errors 24 | BTCErrorIncompatibleSecret = 10001, 25 | BTCErrorInsufficientShares = 10002, 26 | BTCErrorMalformedShare = 10003, 27 | }; -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCErrors.m: -------------------------------------------------------------------------------- 1 | #import "BTCErrors.h" 2 | 3 | NSString* const BTCErrorDomain = @"com.oleganza.CoreBitcoin"; 4 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCHashID.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | /*! 6 | * Converts string transaction or block ID (reversed tx hash in hex format) to binary hash. 7 | */ 8 | NSData* BTCHashFromID(NSString* identifier); 9 | 10 | /*! 11 | * Converts hash of the transaction or block to its string ID (reversed hash in hex format). 12 | */ 13 | NSString* BTCIDFromHash(NSData* hash); 14 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCHashID.m: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCHashID.h" 4 | #import "BTCData.h" 5 | 6 | NSData* BTCHashFromID(NSString* identifier) { 7 | return BTCReversedData(BTCDataFromHex(identifier)); 8 | } 9 | 10 | NSString* BTCIDFromHash(NSData* hash) { 11 | return BTCHexFromData(BTCReversedData(hash)); 12 | } 13 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCMerkleTree.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | @interface BTCMerkleTree : NSObject 6 | 7 | // Returns the merkle root of the tree, a 256-bit hash. 8 | @property(nonatomic, readonly) NSData* merkleRoot; 9 | 10 | // Returns YES if the merkle tree has duplicate items in the tail that cause merkle root collision. 11 | // See also CVE-2012-2459. 12 | @property(nonatomic, readonly) BOOL hasTailDuplicates; 13 | 14 | // Builds a merkle tree based on raw hashes. 15 | - (id) initWithHashes:(NSArray*)hashes; 16 | 17 | // Builds a merkle tree based on transaction hashes. 18 | - (id) initWithTransactions:(NSArray* /* [BTCTransaction] */)transactions; 19 | 20 | // Builds a merkle tree based on BTCHash256 hashes of each NSData item. 21 | - (id) initWithDataItems:(NSArray* /* [NSData] */)dataItems; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCNetwork.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | #import "BTC256.h" 5 | 6 | @class BTCBigNumber; 7 | @class BTCBlock; 8 | @interface BTCNetwork : NSObject 9 | 10 | - (id) initWithName:(NSString*)name; 11 | 12 | // Available networks 13 | 14 | // Main Bitcoin network, singleton instance. 15 | + (BTCNetwork*) mainnet; 16 | 17 | // Testnet3 (current testnet), singleton instance. 18 | + (BTCNetwork*) testnet; 19 | 20 | 21 | 22 | // Network Parameters 23 | // Note: all properties are writable so you can tweak parameters for testing purposes. 24 | // If you do so, you may want to use -copy. 25 | 26 | 27 | // Returns YES if this network is testnet3 (used to tweak certain validation rules). 28 | @property(nonatomic, readonly) BOOL isTestnet; 29 | 30 | // Returns opposite of `isTestnet`. 31 | @property(nonatomic, readonly) BOOL isMainnet; 32 | 33 | // Name of the network ("mainnet", "testnet3" etc) 34 | @property(nonatomic, copy) NSString* name; 35 | 36 | // Name of the network for BIP70 Payment Details ("main", "test" or some custom name used in `-initWithName:`) 37 | @property(nonatomic, copy) NSString* paymentProtocolName; 38 | 39 | // Hash of the genesis block. 40 | @property(nonatomic) NSData* genesisBlockHash; 41 | 42 | // Default port for TCP connections. 43 | @property(nonatomic) uint32_t defaultPort; 44 | 45 | // Maximum target for the proof of work: CBigNum(~uint256(0) >> 32) for mainnet. 46 | @property(nonatomic) BTCBigNumber* proofOfWorkLimit; 47 | 48 | // Array of pairs @[ @(int ), NSData* ] sorted by height. 49 | @property(nonatomic) NSArray* checkpoints; 50 | 51 | 52 | // Returns a checkpoint hash if it exists or BTC256Zero if there is no checkpoint at such height. 53 | - (NSData*) checkpointAtHeight:(int)height; 54 | 55 | // Returns height of checkpoint or -1 if there is no such checkpoint. 56 | - (int) heightForCheckpoint:(NSData*)checkpointHash; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCOutpoint.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | // Outpoint is a reference to a transaction output (byt tx hash and output index). 6 | // It is a part of BTCTransactionInput. 7 | @interface BTCOutpoint : NSObject 8 | 9 | // Outpoint bytes 10 | @property(nonatomic) NSData* outpointData; 11 | 12 | // Hash of the previous transaction. 13 | @property(nonatomic) NSData* txHash; 14 | 15 | // Transaction ID referenced by this input (reversed txHash in hex). 16 | @property(nonatomic) NSString* txID; 17 | 18 | // Index of the previous transaction's output. 19 | @property(nonatomic) uint32_t index; 20 | 21 | - (id) initWithHash:(NSData*)hash index:(uint32_t)index; 22 | 23 | - (id) initWithTxID:(NSString*)txid index:(uint32_t)index; 24 | 25 | @end -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCOutpoint.m: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import "BTCOutpoint.h" 4 | #import "BTCTransaction.h" 5 | #import "BTCHashID.h" 6 | 7 | @implementation BTCOutpoint 8 | 9 | - (id) initWithHash:(NSData*)hash index:(uint32_t)index { 10 | if (hash.length != 32) return nil; 11 | if (self = [super init]) { 12 | _txHash = hash; 13 | _index = index; 14 | } 15 | return self; 16 | } 17 | 18 | - (id) initWithTxID:(NSString*)txid index:(uint32_t)index { 19 | NSData* hash = BTCHashFromID(txid); 20 | return [self initWithHash:hash index:index]; 21 | } 22 | 23 | - (NSData*) outpointData { 24 | NSMutableData* result = [_txHash mutableCopy]; 25 | [result appendBytes:&_index length:4]; 26 | return result; 27 | } 28 | 29 | - (NSString*) txID { 30 | return BTCIDFromHash(self.txHash); 31 | } 32 | 33 | - (void) setTxID:(NSString *)txID { 34 | self.txHash = BTCHashFromID(txID); 35 | } 36 | 37 | - (NSUInteger) hash { 38 | const NSUInteger* words = _txHash.bytes; 39 | return words[0] + self.index; 40 | } 41 | 42 | - (BOOL) isEqual:(BTCOutpoint*)object { 43 | return [self.txHash isEqual:object.txHash] && self.index == object.index; 44 | } 45 | 46 | - (id) copyWithZone:(NSZone *)zone { 47 | return [[BTCOutpoint alloc] initWithHash:_txHash index:_index]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCProtocolBuffers.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | // An API to parse and encode protocol buffers. 6 | @interface BTCProtocolBuffers : NSObject 7 | 8 | // Reading 9 | 10 | // Returns a variable-length integer value at a given offset in source data. 11 | + (uint64_t) varIntAtOffset:(NSInteger*)offset fromData:(NSData*)src; 12 | 13 | // Returns a length-delimited data at a given offset in source data. 14 | + (NSData *) lenghtDelimitedDataAtOffset:(NSInteger *)offset fromData:(NSData*)src; 15 | 16 | // Returns either int or data depending on field type, and returns a field key. 17 | + (NSInteger) fieldAtOffset:(NSInteger *)offset int:(uint64_t *)i data:(NSData **)d fromData:(NSData*)src; 18 | 19 | // Returns either int or fixed64 or data depending on field type, and returns a field key. 20 | + (NSInteger) fieldAtOffset:(NSInteger *)offset int:(uint64_t *)i fixed32:(uint32_t *)fixed32 fixed64:(uint64_t *)fixed64 data:(NSData **)d fromData:(NSData*)src; 21 | 22 | // Writing 23 | 24 | + (void) writeInt:(uint64_t)i withKey:(NSInteger)key toData:(NSMutableData*)dst; 25 | + (void) writeFixed32:(uint32_t)i withKey:(NSInteger)key toData:(NSMutableData*)dst; 26 | + (void) writeFixed64:(uint64_t)i withKey:(NSInteger)key toData:(NSMutableData*)dst; 27 | + (void) writeLengthDelimitedData:(NSData*)data toData:(NSMutableData*)dst; 28 | + (void) writeData:(NSData*)d withKey:(NSInteger)key toData:(NSMutableData*)dst; 29 | + (void) writeString:(NSString*)string withKey:(NSInteger)key toData:(NSMutableData*)dst; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCProtocolSerialization.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | // A collection of routines dealing with parsing and writing various protocol messages. 6 | @interface BTCProtocolSerialization : NSObject 7 | 8 | // This implementation of variable-length integer is known as "CompactSize" in Satoshi code (BitcoinQT). 9 | // 10 | // Value Storage length Format 11 | // < 0xfd 1 uint8_t 12 | // <= 0xffff 3 0xfd followed by the value as uint16_t 13 | // <= 0xffffffff 5 0xfe followed by the value as uint32_t 14 | // > 0xffffffff 9 0xff followed by the value as uint64_t 15 | // 16 | // Note: BitcoinQT later added VarInt which is different, more compact format 17 | // used in block storage. VarInt is not a part of the protocol and is not implemented here. 18 | 19 | // Attempts to read integer from data and returns amount of bytes read. 20 | // In case of error, returns 0. 21 | + (NSUInteger) readVarInt:(uint64_t*)valueOut fromData:(NSData*)data; 22 | + (NSUInteger) readVarInt:(uint64_t*)valueOut fromStream:(NSInputStream*)stream; 23 | 24 | // Attempts to read string prepended by its length in varInt format. 25 | // On success, returns data. On failure, returns nil. 26 | // lengthOut is an optional out parameter that contains total bytes read (including the length prefix) 27 | + (NSData*) readVarStringFromData:(NSData*)data; 28 | + (NSData*) readVarStringFromData:(NSData*)data readBytes:(NSInteger*)lengthOut; 29 | + (NSData*) readVarStringFromStream:(NSInputStream*)stream; 30 | 31 | // Encodes value in a varint binary form. 32 | + (NSData*) dataForVarInt:(uint64_t)value; 33 | 34 | // Prepends binary string with its length in varInt format. 35 | + (NSData*) dataForVarString:(NSData*)binaryString; 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCQRCode.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | #if TARGET_OS_IPHONE 5 | #import 6 | #import 7 | #endif 8 | 9 | @interface BTCQRCode : NSObject 10 | 11 | #if TARGET_OS_IPHONE 12 | /*! 13 | * Returns a QR code image with a given size. 14 | * The `string` is typically a bitcoin address in Base58Check format. 15 | */ 16 | + (UIImage*) imageForString:(NSString*)string size:(CGSize)size scale:(CGFloat)scale; 17 | 18 | /*! 19 | * Returns a QR code image with a given size. 20 | * The `url` is typically a bitcoin payment request "bitcoin:
?amount=..." 21 | */ 22 | + (UIImage*) imageForURL:(NSURL*)url size:(CGSize)size scale:(CGFloat)scale; 23 | 24 | /*! 25 | * Returns a scanning view and retains a detection block. 26 | * 27 | * Block is called for every QR code detected. To stop recognition, remove view from the window. 28 | * 29 | * Block is released when view is removed from window. 30 | */ 31 | + (UIView*) scannerViewWithBlock:(void(^)(NSString* message))detectionBlock; 32 | 33 | 34 | /*! 35 | * Returns a scanning view and retains a detection block. 36 | * 37 | * Block is called for every QR code detected. To stop recognition, remove view from the window. 38 | * 39 | * Block is released when view is removed from window. 40 | * 41 | * The device position helps selecting the camera (front or back) 42 | */ 43 | + (UIView*) scannerViewUsingDevice:(AVCaptureDevicePosition) devicePosition 44 | orientation:(AVCaptureVideoOrientation) orientation 45 | block:(void(^)(NSString* message))detectionBlock; 46 | #endif 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/BTCSecretSharing.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | 5 | typedef NS_ENUM(NSInteger, BTCSecretSharingVersion) { 6 | // Identifies configuration for compact 128-bit secrets with up to 16 shares. 7 | BTCSecretSharingVersionCompact96 = 96, 8 | BTCSecretSharingVersionCompact104 = 104, 9 | BTCSecretSharingVersionCompact128 = 128, 10 | }; 11 | 12 | @class BTCBigNumber; 13 | @interface BTCSecretSharing : NSObject 14 | 15 | @property(nonatomic, readonly) BTCSecretSharingVersion version; 16 | @property(nonatomic, readonly, nonnull) BTCBigNumber* order; 17 | @property(nonatomic, readonly) NSInteger bitlength; 18 | 19 | - (id __nonnull) initWithVersion:(BTCSecretSharingVersion)version; 20 | 21 | - (NSArray* __nullable) splitSecret:(NSData* __nonnull)secret threshold:(NSInteger)m shares:(NSInteger)n error:(NSError* __nullable * __nullable)errorOut; 22 | 23 | - (NSData* __nullable) joinShares:(NSArray* __nonnull)shares error:(NSError* __nullable * __nullable)errorOut; 24 | 25 | @end -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/CoreBitcoin.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev "oleganza@gmail.com", WTFPL. 2 | 3 | #import "BTCPaymentMethodDetails.h" 4 | #import "BTCProcessor.h" 5 | #import "BTCCurvePoint.h" 6 | #import "BTCData.h" 7 | #import "BTCMerkleTree.h" 8 | #import "BTCOutpoint.h" 9 | #import "BTCProtocolBuffers.h" 10 | #import "BTC256.h" 11 | #import "BTCAddress.h" 12 | #import "BTCPaymentMethod.h" 13 | #import "BTCHashID.h" 14 | #import "BTCCurrencyConverter.h" 15 | #import "BTCScript.h" 16 | #import "BTCPaymentRequest.h" 17 | #import "BTCScriptTestData.h" 18 | #import "BTCTransactionOutput.h" 19 | #import "BTCAddressSubclass.h" 20 | #import "BTCKey.h" 21 | #import "BTCEncryptedMessage.h" 22 | #import "BTCBase58.h" 23 | #import "BTCPaymentMethodRequest.h" 24 | #import "BTCPaymentProtocol.h" 25 | #import "BTCErrors.h" 26 | #import "BTCBlindSignature.h" 27 | #import "BTCQRCode.h" 28 | #import "BTCAssetID.h" 29 | #import "BTCTransactionBuilder.h" 30 | #import "BTCAssetType.h" 31 | #import "BTCKeychain.h" 32 | #import "BTCEncryptedBackup.h" 33 | #import "BTCBlock.h" 34 | #import "BTCBlockHeader.h" 35 | #import "BTCNumberFormatter.h" 36 | #import "BTCBlockchainInfo.h" 37 | #import "BTCBigNumber.h" 38 | #import "BTCTransaction.h" 39 | #import "BTCUnitsAndLimits.h" 40 | #import "BTCFancyEncryptedMessage.h" 41 | #import "BTCOpcode.h" 42 | #import "BTCPriceSource.h" 43 | #import "BTCSecretSharing.h" 44 | #import "BTCSignatureHashType.h" 45 | #import "BTCMnemonic.h" 46 | #import "BTCProtocolSerialization.h" 47 | #import "BTCNetwork.h" 48 | #import "BTCScriptMachine.h" 49 | #import "BTCTransactionInput.h" 50 | #import "BTCAssetAddress.h" 51 | #import "BTCBitcoinURL.h" 52 | #import "BTCChainCom.h" 53 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/NS+BTCBase58.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | #import "BTCBase58.h" 5 | 6 | // These categories are optional and provided for convenience only. 7 | // For documentation look into BTCBase58.h. 8 | // They are also used in CoreBitcoin unit tests. 9 | @interface NSString (BTCBase58) 10 | 11 | // Returns data for Base58 string without checksum 12 | // Data is mutable so you can clear sensitive information as soon as possible. 13 | - (NSMutableData*) dataFromBase58; 14 | 15 | // Returns data for Base58 string with checksum 16 | - (NSMutableData*) dataFromBase58Check; 17 | 18 | @end 19 | 20 | @interface NSMutableData (BTCBase58) 21 | 22 | // Returns data for Base58 string without checksum 23 | // Data is mutable so you can clear sensitive information as soon as possible. 24 | + (NSMutableData*) dataFromBase58CString:(const char*)cstring; 25 | 26 | // Returns data for Base58 string with checksum 27 | + (NSMutableData*) dataFromBase58CheckCString:(const char*)cstring; 28 | 29 | @end 30 | 31 | @interface NSData (BTCBase58) 32 | 33 | // String in Base58 without checksum, you need to free it yourself. 34 | // It's mutable so you can clear it securely yourself. 35 | - (char*) base58CString; 36 | 37 | // String in Base58 with checksum, you need to free it yourself. 38 | // It's mutable so you can clear it securely yourself. 39 | - (char*) base58CheckCString; 40 | 41 | // String in Base58 without checksum 42 | - (NSString*) base58String; 43 | 44 | // String in Base58 with checksum 45 | - (NSString*) base58CheckString; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/NS+BTCBase58.m: -------------------------------------------------------------------------------- 1 | // Oleg Andreev 2 | 3 | #import "NS+BTCBase58.h" 4 | 5 | // TODO. 6 | 7 | @implementation NSString (BTCBase58) 8 | 9 | - (NSMutableData*) dataFromBase58 { return BTCDataFromBase58(self); } 10 | - (NSMutableData*) dataFromBase58Check { return BTCDataFromBase58Check(self); } 11 | @end 12 | 13 | 14 | @implementation NSMutableData (BTCBase58) 15 | 16 | + (NSMutableData*) dataFromBase58CString:(const char*)cstring { 17 | return BTCDataFromBase58CString(cstring); 18 | } 19 | 20 | + (NSMutableData*) dataFromBase58CheckCString:(const char*)cstring { 21 | return BTCDataFromBase58CheckCString(cstring); 22 | } 23 | 24 | @end 25 | 26 | 27 | @implementation NSData (BTCBase58) 28 | 29 | - (char*) base58CString { 30 | return BTCBase58CStringWithData(self); 31 | } 32 | 33 | - (char*) base58CheckCString { 34 | return BTCBase58CheckCStringWithData(self); 35 | } 36 | 37 | - (NSString*) base58String { 38 | return BTCBase58StringWithData(self); 39 | } 40 | 41 | - (NSString*) base58CheckString { 42 | return BTCBase58CheckStringWithData(self); 43 | } 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Vendor/CoreBitcoin/NSData+BTCData.h: -------------------------------------------------------------------------------- 1 | // CoreBitcoin by Oleg Andreev , WTFPL. 2 | 3 | #import 4 | #import "BTCData.h" 5 | 6 | // This category is for user's convenience only. 7 | // For documentation look into BTCData.h. 8 | // If you link CoreBitcoin library without categories enabled, nothing will break. 9 | // This is also used in unit tests in CoreBitcoin. 10 | @interface NSData (BTCData) 11 | 12 | // Core hash functions 13 | - (NSData*) SHA1; 14 | - (NSData*) SHA256; 15 | - (NSData*) BTCHash256; // SHA256(SHA256(self)) aka Hash or Hash256 in BitcoinQT 16 | 17 | #if BTCDataRequiresOpenSSL 18 | - (NSData*) RIPEMD160; 19 | - (NSData*) BTCHash160; // RIPEMD160(SHA256(self)) aka Hash160 in BitcoinQT 20 | #endif 21 | 22 | // Formats data as a lowercase hex string 23 | - (NSString*) hex; 24 | - (NSString*) uppercaseHex; 25 | 26 | - (NSString*) hexString DEPRECATED_ATTRIBUTE; 27 | - (NSString*) hexUppercaseString DEPRECATED_ATTRIBUTE; 28 | 29 | 30 | // Encrypts/decrypts data using the key. 31 | // IV should either be nil or at least 128 bits long 32 | + (NSMutableData*) encryptData:(NSData*)data key:(NSData*)key iv:(NSData*)initializationVector; 33 | + (NSMutableData*) decryptData:(NSData*)data key:(NSData*)key iv:(NSData*)initializationVector; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Vendor/libscrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Joshua Small 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | 10 | -------------------------------------------------------------------------------- /Vendor/libscrypt/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | LIBDIR ?= $(PREFIX)/lib 3 | INCLUDEDIR ?= $(PREFIX)/include 4 | MAKE_DIR ?= install -d 5 | INSTALL_DATA ?= install 6 | 7 | CC?=gcc 8 | CFLAGS?=$(CFLAGS_EXTRA) -D_FORTIFY_SOURCE=2 -fPIC 9 | LDFLAGS?=$(LDFLAGS_EXTRA) -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version 10 | CFLAGS_EXTRA?=-Wl,-rpath=. -O2 -Wall -g -fstack-protector 11 | LDFLAGS_EXTRA?=-Wl,-z,relro 12 | 13 | all: reference 14 | 15 | OBJS= crypto_scrypt-nosse.o sha256.o crypto-mcf.o b64.o crypto-scrypt-saltgen.o crypto_scrypt-check.o crypto_scrypt-hash.o slowequals.o 16 | 17 | libscrypt.so.0: $(OBJS) 18 | $(CC) $(LDFLAGS) -shared -o libscrypt.so.0 $(OBJS) -lm -lc 19 | ar rcs libscrypt.a $(OBJS) 20 | 21 | reference: libscrypt.so.0 main.o crypto_scrypt-hexconvert.o 22 | ln -s -f libscrypt.so.0 libscrypt.so 23 | $(CC) -o reference main.o b64.o crypto_scrypt-hexconvert.o $(CFLAGS) $(LDFLAGS_EXTRA) -L. -lscrypt 24 | 25 | clean: 26 | rm -f *.o reference libscrypt.so* libscrypt.a endian.h 27 | 28 | check: all 29 | LD_LIBRARY_PATH=. ./reference 30 | 31 | devtest: 32 | splint crypto_scrypt-hexconvert.c 33 | splint crypto-mcf.c crypto_scrypt-check.c crypto_scrypt-hash.c -unrecog 34 | splint crypto-scrypt-saltgen.c +posixlib -compdef 35 | valgrind ./reference 36 | 37 | asan: main.c 38 | clang -O1 -g -fsanitize=address -fno-omit-frame-pointer *.c -o asantest 39 | ./asantest 40 | scan-build clang -O1 -g -fsanitize=undefined -fno-omit-frame-pointer *.c -o asantest 41 | ./asantest 42 | rm -f asantest 43 | 44 | install: libscrypt.so.0 45 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 46 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR) 47 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.so 48 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 49 | 50 | install-osx: libscrypt.so.0 51 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 52 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 53 | cd $(DESTDIR)$(LIBDIR) && install_name_tool -id $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 54 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.dylib 55 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 56 | 57 | install-static: libscrypt.a 58 | $(INSTALL_DATA) -pm 0644 libscrypt.a $(DESTDIR)$(LIBDIR) 59 | -------------------------------------------------------------------------------- /Vendor/libscrypt/b64.h: -------------------------------------------------------------------------------- 1 | 2 | /* BASE64 libraries used internally - should not need to be packaged */ 3 | #include 4 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1) 5 | #define b64_decode_len(A) (A / 4 * 3 + 2) 6 | 7 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength, 8 | /*@out@*/ char *target, size_t targetsize); 9 | int libscrypt_b64_decode(char const *src, /*@out@*/ unsigned char *target, 10 | size_t targetsize); 11 | -------------------------------------------------------------------------------- /Vendor/libscrypt/crypto-mcf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libscrypt.h" 6 | 7 | /* ilog2 for powers of two */ 8 | static uint32_t scrypt_ilog2(uint32_t n) 9 | { 10 | #ifndef S_SPLINT_S 11 | 12 | /* Check for a valid power of two */ 13 | if (n < 2 || (n & (n - 1))) 14 | return -1; 15 | #endif 16 | uint32_t t = 1; 17 | while (((uint32_t)1 << t) < n) 18 | { 19 | if(t > SCRYPT_SAFE_N) 20 | return (uint32_t) -1; /* Check for insanity */ 21 | t++; 22 | } 23 | 24 | return t; 25 | } 26 | 27 | #ifdef _MSC_VER 28 | #define SNPRINTF _snprintf 29 | #else 30 | #define SNPRINTF snprintf 31 | #endif 32 | 33 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, 34 | const char *hash, char *mcf) 35 | { 36 | 37 | uint32_t t, params; 38 | int s; 39 | 40 | if(!mcf || !hash) 41 | return 0; 42 | /* Although larger values of r, p are valid in scrypt, this mcf format 43 | * limits to 8 bits. If your number is larger, current computers will 44 | * struggle 45 | */ 46 | if(r > (uint8_t)(-1) || p > (uint8_t)(-1)) 47 | return 0; 48 | 49 | t = scrypt_ilog2(N); 50 | if (t < 1) 51 | return 0; 52 | 53 | params = (r << 8) + p; 54 | params += (uint32_t)t << 16; 55 | 56 | /* Using snprintf - not checking for overflows. We've already 57 | * determined that mcf should be defined as at least SCRYPT_MCF_LEN 58 | * in length 59 | */ 60 | s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash); 61 | if (s >= SCRYPT_MCF_LEN) 62 | return 0; 63 | 64 | return 1; 65 | } 66 | -------------------------------------------------------------------------------- /Vendor/libscrypt/crypto-scrypt-saltgen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* Disable on Windows, there is no /dev/urandom. 8 | Link-time error is better than runtime error. */ 9 | #ifndef _WIN32 10 | 11 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ 12 | #include 13 | #endif 14 | 15 | #define RNGDEV "/dev/urandom" 16 | 17 | int libscrypt_salt_gen(uint8_t *salt, size_t len) 18 | { 19 | unsigned char buf[len]; 20 | size_t data_read = 0; 21 | int urandom = open(RNGDEV, O_RDONLY); 22 | 23 | if (urandom < 0) 24 | { 25 | return -1; 26 | } 27 | 28 | while (data_read < len) { 29 | ssize_t result = read(urandom, buf + data_read, len - data_read); 30 | 31 | if (result < 0) 32 | { 33 | if (errno == EINTR || errno == EAGAIN) { 34 | continue; 35 | } 36 | 37 | else { 38 | (void)close(urandom); 39 | return -1; 40 | } 41 | } 42 | 43 | data_read += result; 44 | } 45 | 46 | /* Failures on close() shouldn't occur with O_RDONLY */ 47 | (void)close(urandom); 48 | 49 | memcpy(salt, buf, len); 50 | 51 | return 0; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Vendor/libscrypt/crypto_scrypt-hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "libscrypt.h" 8 | 9 | int libscrypt_hash(char *dst, const char *passphrase, uint32_t N, uint8_t r, 10 | uint8_t p) 11 | { 12 | 13 | int retval; 14 | uint8_t salt[SCRYPT_SALT_LEN]; 15 | uint8_t hashbuf[SCRYPT_HASH_LEN]; 16 | char outbuf[256]; 17 | char saltbuf[256]; 18 | 19 | if(libscrypt_salt_gen(salt, SCRYPT_SALT_LEN) == -1) 20 | { 21 | return 0; 22 | } 23 | 24 | retval = libscrypt_scrypt((const uint8_t*)passphrase, strlen(passphrase), 25 | (uint8_t*)salt, SCRYPT_SALT_LEN, N, r, p, hashbuf, sizeof(hashbuf)); 26 | if(retval == -1) 27 | return 0; 28 | 29 | retval = libscrypt_b64_encode((unsigned char*)hashbuf, sizeof(hashbuf), 30 | outbuf, sizeof(outbuf)); 31 | if(retval == -1) 32 | return 0; 33 | 34 | retval = libscrypt_b64_encode((unsigned char *)salt, sizeof(salt), 35 | saltbuf, sizeof(saltbuf)); 36 | if(retval == -1) 37 | return 0; 38 | 39 | retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst); 40 | if(retval != 1) 41 | return 0; 42 | 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /Vendor/libscrypt/crypto_scrypt-hexconvert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* The hexconvert function is only used to test reference vectors against 7 | * known answers. The contents of this file are therefore a component 8 | * to assist with test harnesses only 9 | */ 10 | 11 | int libscrypt_hexconvert(uint8_t *buf, size_t s, char *outbuf, size_t obs) 12 | { 13 | 14 | size_t i; 15 | int len = 0; 16 | 17 | if (!buf || s < 1 || obs < (s * 2 + 1)) 18 | return 0; 19 | 20 | memset(outbuf, 0, obs); 21 | 22 | 23 | for(i=0; i<=(s-1); i++) 24 | { 25 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results 26 | * and can't be used. Using offests like this makes snprintf 27 | * nontrivial. we therefore have use inescure sprintf() and 28 | * lengths checked elsewhere (start of function) */ 29 | /*@ -bufferoverflowhigh @*/ 30 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]); 31 | } 32 | 33 | return 1; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Vendor/libscrypt/crypto_scrypt-hexconvert.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Converts a binary string to a hex representation of that string 6 | * outbuf must have size of at least buf * 2 + 1. 7 | */ 8 | int libscrypt_hexconvert(const uint8_t *buf, size_t s, char *outbuf, 9 | size_t obs); 10 | -------------------------------------------------------------------------------- /Vendor/libscrypt/libscrypt.version: -------------------------------------------------------------------------------- 1 | libscrypt { 2 | global: libscrypt_check; 3 | libscrypt_hash; 4 | libscrypt_mcf; 5 | libscrypt_salt_gen; 6 | libscrypt_scrypt; 7 | local: *; 8 | }; 9 | -------------------------------------------------------------------------------- /Vendor/libscrypt/slowequals.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Implements a constant time version of strcmp() 4 | * Will return 1 if a and b are equal, 0 if they are not */ 5 | int slow_equals(const char* a, const char* b) 6 | { 7 | size_t lena, lenb, diff, i; 8 | lena = strlen(a); 9 | lenb = strlen(b); 10 | diff = strlen(a) ^ strlen(b); 11 | 12 | for(i=0; i 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | secp256k1 9 | CFBundleIdentifier 10 | org.secp256k1lib 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | FMWK 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0.0 19 | 20 | 21 | -------------------------------------------------------------------------------- /Vendor/secp256k1/secp256k1.framework/Versions/A/Resources/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Vendor/secp256k1/secp256k1.framework/Versions/A/secp256k1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/consenlabs/token-core-ios/b896f0cacb9530894cd18ec3843c4ca630d8a867/Vendor/secp256k1/secp256k1.framework/Versions/A/secp256k1 -------------------------------------------------------------------------------- /Vendor/secp256k1/secp256k1.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Vendor/secp256k1/secp256k1.framework/secp256k1: -------------------------------------------------------------------------------- 1 | Versions/Current/secp256k1 --------------------------------------------------------------------------------