├── .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
--------------------------------------------------------------------------------