@authon/react-native-wallet 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +34 -4
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/dev/authon/reactnative/wallet/AuthonWalletModule.kt +57 -3
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/AndroidCapabilityProbe.kt +86 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/AuthonWallet.kt +29 -2
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Bitcoin.kt +296 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Chains.kt +157 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Der.kt +17 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Encodings.kt +133 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Http.kt +6 -2
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/KeystoreDeviceStore.kt +27 -23
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Solana.kt +195 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Tron.kt +184 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletApi.kt +16 -8
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletCapabilities.kt +91 -0
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletError.kt +18 -2
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletOps.kt +103 -1
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletTypes.kt +8 -1
- package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Xrp.kt +193 -0
- package/build/client.d.ts +18 -2
- package/build/client.d.ts.map +1 -1
- package/build/client.js +88 -6
- package/build/client.js.map +1 -1
- package/build/errors.d.ts +8 -1
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js +7 -1
- package/build/errors.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/native.d.ts +5 -1
- package/build/native.d.ts.map +1 -1
- package/build/native.js.map +1 -1
- package/build/types.d.ts +47 -1
- package/build/types.d.ts.map +1 -1
- package/ios/AuthonReactNativeWallet.podspec +6 -2
- package/ios/AuthonWalletModule.swift +46 -3
- package/ios/vendor/AuthonWallet/AuthonWallet.swift +24 -4
- package/ios/vendor/AuthonWallet/Capabilities.swift +149 -0
- package/ios/vendor/AuthonWallet/Chains/Bitcoin.swift +296 -0
- package/ios/vendor/AuthonWallet/Chains/Solana.swift +207 -0
- package/ios/vendor/AuthonWallet/Chains/Tron.swift +181 -0
- package/ios/vendor/AuthonWallet/Chains/XRP.swift +191 -0
- package/ios/vendor/AuthonWallet/Crypto/Chains.swift +278 -0
- package/ios/vendor/AuthonWallet/Crypto/Secp256k1.swift +24 -0
- package/ios/vendor/AuthonWallet/Wallet/WalletAPI.swift +19 -8
- package/ios/vendor/AuthonWallet/Wallet/WalletOps.swift +101 -2
- package/ios/vendor/AuthonWallet/WalletError.swift +32 -2
- package/ios/vendor/CKeccak/README.md +6 -3
- package/ios/vendor/CKeccak/include/ckeccak.h +4 -0
- package/ios/vendor/CKeccak/ripemd160.c +343 -0
- package/ios/vendor/CKeccak/ripemd160.h +22 -0
- package/ios/vendor/CMonocypher/LICENCE.md +173 -0
- package/ios/vendor/CMonocypher/README.md +27 -0
- package/ios/vendor/CMonocypher/include/monocypher-ed25519.h +140 -0
- package/ios/vendor/CMonocypher/include/monocypher.h +321 -0
- package/ios/vendor/CMonocypher/monocypher-ed25519.c +500 -0
- package/ios/vendor/CMonocypher/monocypher.c +2956 -0
- package/ios/vendor/GENERATED.md +1 -1
- package/package.json +3 -2
- package/src/client.ts +90 -6
- package/src/errors.ts +7 -1
- package/src/index.ts +5 -0
- package/src/native.ts +4 -2
- package/src/types.ts +52 -1
|
@@ -45,6 +45,9 @@ public struct WalletAccount: Equatable, Sendable {
|
|
|
45
45
|
public var index: Int
|
|
46
46
|
public var path: String
|
|
47
47
|
public var address: String
|
|
48
|
+
public var chain: WalletChain
|
|
49
|
+
/// XRP only: the compressed public key (uppercase hex) to put in SigningPubKey.
|
|
50
|
+
public var publicKey: String? = nil
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
/// Which account signs. Account 0 is the wallet address the server knows; another account
|
|
@@ -309,7 +312,7 @@ struct WalletOps {
|
|
|
309
312
|
return try fn(account)
|
|
310
313
|
}
|
|
311
314
|
|
|
312
|
-
func accounts(_ session: String, start: Int = 0, count: Int = 1) async throws -> [WalletAccount] {
|
|
315
|
+
func accounts(_ session: String, start: Int = 0, count: Int = 1, chain: WalletChain = .evm) async throws -> [WalletAccount] {
|
|
313
316
|
guard WalletShares.isAccountIndex(start), count >= 1, WalletShares.isAccountIndex(start + count - 1) else {
|
|
314
317
|
throw WalletError(.invalidRequest, "start..start+count-1 must stay within 0..\(WalletShares.maxAccountIndex)")
|
|
315
318
|
}
|
|
@@ -324,11 +327,18 @@ struct WalletOps {
|
|
|
324
327
|
}
|
|
325
328
|
secret = try WalletShares.assemble(device, company)
|
|
326
329
|
guard try WalletShares.address(secret).lowercased() == local.wallet.address.lowercased() else { throw WalletError(.addressMismatch) }
|
|
330
|
+
if chain != .evm {
|
|
331
|
+
let list = try ChainAddresses.addresses(secret, chain: chain, start: start, count: count)
|
|
332
|
+
let keys = chain == .xrp ? try ChainAddresses.xrpPublicKeys(secret, start: start, count: count) : nil
|
|
333
|
+
return list.enumerated().map {
|
|
334
|
+
WalletAccount(index: start + $0.offset, path: chain.path(start + $0.offset), address: $0.element, chain: chain, publicKey: keys?[$0.offset])
|
|
335
|
+
}
|
|
336
|
+
}
|
|
327
337
|
if !WalletShares.isHdSecret(secret) && (start != 0 || count != 1) {
|
|
328
338
|
throw WalletError(.accountUnavailable, "this wallet has only account 0")
|
|
329
339
|
}
|
|
330
340
|
let list = try WalletShares.addresses(secret, start: start, count: count)
|
|
331
|
-
return list.enumerated().map { WalletAccount(index: start + $0.offset, path: WalletShares.evmPath(start + $0.offset), address: $0.element) }
|
|
341
|
+
return list.enumerated().map { WalletAccount(index: start + $0.offset, path: WalletShares.evmPath(start + $0.offset), address: $0.element, chain: .evm) }
|
|
332
342
|
}
|
|
333
343
|
|
|
334
344
|
private static func reserved() -> WalletError {
|
|
@@ -393,6 +403,95 @@ struct WalletOps {
|
|
|
393
403
|
return try await withSecret(session, account: account, summary: { Summaries.transaction(tx) }) { try $0.signTransaction(evmTx) }
|
|
394
404
|
}
|
|
395
405
|
|
|
406
|
+
/// Signs a transaction on a chain other than EVM (section 12; Solana and TRON). The summary is
|
|
407
|
+
/// built from the payload and the expected address before the company share is requested.
|
|
408
|
+
func signChainTransaction(_ session: String, chain: WalletChain, account index: Int, address: String, payload: JSONValue) async throws -> [String: String] {
|
|
409
|
+
guard WalletShares.isAccountIndex(index) else {
|
|
410
|
+
throw WalletError(.invalidRequest, "account must be an integer 0..\(WalletShares.maxAccountIndex)")
|
|
411
|
+
}
|
|
412
|
+
guard !address.isEmpty else { throw WalletError(.invalidRequest, "address of the signing account required") }
|
|
413
|
+
let summary: SignSummary
|
|
414
|
+
let sign: ([UInt8]) throws -> [String: String]
|
|
415
|
+
switch chain {
|
|
416
|
+
case .solana:
|
|
417
|
+
guard case .string(let b64) = payload["message"] ?? .null, let message = Bytes.fromBase64(b64) else {
|
|
418
|
+
throw WalletError(.invalidRequest, "payload.message (base64) required")
|
|
419
|
+
}
|
|
420
|
+
let network: String
|
|
421
|
+
if case .string(let cluster) = payload["cluster"] ?? .null, cluster.utf16.count <= 32 {
|
|
422
|
+
network = "Solana \(cluster)"
|
|
423
|
+
} else {
|
|
424
|
+
network = "Solana (network chosen by the app)"
|
|
425
|
+
}
|
|
426
|
+
summary = try Solana.summarize(try Solana.parse(message), signer: address, network: network)
|
|
427
|
+
sign = { secret in
|
|
428
|
+
var key = try Solana.privateKey(secret, index: index)
|
|
429
|
+
defer { key.wipe() }
|
|
430
|
+
let signed = Solana.sign(message, privateKey: key)
|
|
431
|
+
guard signed.address == address else { throw WalletError(.addressMismatch) }
|
|
432
|
+
return ["signature": signed.signature]
|
|
433
|
+
}
|
|
434
|
+
case .bitcoin, .bitcoinTestnet:
|
|
435
|
+
guard case .string(let b64) = payload["psbt"] ?? .null, let bytes = Bytes.fromBase64(b64) else {
|
|
436
|
+
throw WalletError(.invalidRequest, "payload.psbt (base64) required")
|
|
437
|
+
}
|
|
438
|
+
let psbt = try Bitcoin.parse(bytes)
|
|
439
|
+
summary = try Bitcoin.summarize(psbt, signer: address, chain: chain)
|
|
440
|
+
sign = { secret in
|
|
441
|
+
var key = try ChainAddresses.secpPrivateKey(secret, chain: chain, index: index)
|
|
442
|
+
defer { key.wipe() }
|
|
443
|
+
guard try ChainAddresses.secpAddress(chain, privateKey: key) == address else { throw WalletError(.addressMismatch) }
|
|
444
|
+
return try Bitcoin.sign(psbt, privateKey: key)
|
|
445
|
+
}
|
|
446
|
+
case .xrp:
|
|
447
|
+
guard case .string(let hex) = payload["txBlobHex"] ?? .null, Self.isPlainHex(hex), let blob = Bytes.fromHex(hex) else {
|
|
448
|
+
throw WalletError(.invalidRequest, "payload.txBlobHex (encodeForSigning output) required")
|
|
449
|
+
}
|
|
450
|
+
let tx = try XRP.parse(blob)
|
|
451
|
+
guard tx.account == address else { throw WalletError(.addressMismatch, "the transaction account is not the signing account") }
|
|
452
|
+
summary = try XRP.summarize(tx, signer: address, signerPublicKey: tx.signingPubKey!)
|
|
453
|
+
sign = { secret in
|
|
454
|
+
var key = try ChainAddresses.secpPrivateKey(secret, chain: .xrp, index: index)
|
|
455
|
+
defer { key.wipe() }
|
|
456
|
+
let pub = try Secp256k1.publicKey(of: key, compressed: true)
|
|
457
|
+
guard try XRP.address(publicKey: pub) == address, pub == tx.signingPubKey else { throw WalletError(.addressMismatch) }
|
|
458
|
+
return try XRP.sign(blob, privateKey: key)
|
|
459
|
+
}
|
|
460
|
+
case .evm:
|
|
461
|
+
throw WalletError(.unsupportedType, "use signTransaction for EVM")
|
|
462
|
+
case .tron:
|
|
463
|
+
guard case .string(let hex) = payload["rawDataHex"] ?? .null, Self.isPlainHex(hex), let raw = Bytes.fromHex(hex) else {
|
|
464
|
+
throw WalletError(.invalidRequest, "payload.rawDataHex required")
|
|
465
|
+
}
|
|
466
|
+
summary = try Tron.summarize(try Tron.parse(raw), signer: address)
|
|
467
|
+
sign = { secret in
|
|
468
|
+
var key = try ChainAddresses.secpPrivateKey(secret, chain: .tron, index: index)
|
|
469
|
+
defer { key.wipe() }
|
|
470
|
+
guard try ChainAddresses.secpAddress(.tron, privateKey: key) == address else { throw WalletError(.addressMismatch) }
|
|
471
|
+
return try Tron.sign(raw, privateKey: key)
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
let local = try await requireLocal(session)
|
|
475
|
+
if ctx.confirmSigning { try await approve(summary) }
|
|
476
|
+
if let auth = ctx.deviceAuthenticator { try await auth.authenticate(reason: summary.title) }
|
|
477
|
+
var company = try await fetchCompanyShare(session, local.record)
|
|
478
|
+
var device = try ctx.store.open(local.record)
|
|
479
|
+
var secret = [UInt8]()
|
|
480
|
+
defer {
|
|
481
|
+
secret.wipe()
|
|
482
|
+
device.wipe()
|
|
483
|
+
company.wipe()
|
|
484
|
+
}
|
|
485
|
+
secret = try WalletShares.assemble(device, company)
|
|
486
|
+
guard try WalletShares.address(secret).lowercased() == local.wallet.address.lowercased() else { throw WalletError(.addressMismatch) }
|
|
487
|
+
return try sign(secret)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/// /^([0-9a-fA-F]{2})+$/
|
|
491
|
+
static func isPlainHex(_ s: String) -> Bool {
|
|
492
|
+
!s.isEmpty && s.count % 2 == 0 && s.utf8.allSatisfy { (0x30...0x39).contains($0) || (0x41...0x46).contains($0) || (0x61...0x66).contains($0) }
|
|
493
|
+
}
|
|
494
|
+
|
|
396
495
|
// MARK: - Backup
|
|
397
496
|
|
|
398
497
|
private func writeBackup(_ session: String, upgrade: Bool) async throws -> ProtectResult {
|
|
@@ -34,16 +34,46 @@ public enum WalletErrorCode: String, Sendable, CaseIterable {
|
|
|
34
34
|
case accountUnavailable = "ACCOUNT_UNAVAILABLE"
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
extension WalletErrorCode {
|
|
38
|
+
/// Whether retrying the same call can succeed (docs/wallet/NATIVE.md section 10).
|
|
39
|
+
public var retryable: Bool {
|
|
40
|
+
switch self {
|
|
41
|
+
case .apiError, .rateLimited, .walletPending: return true
|
|
42
|
+
default: return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
public struct WalletError: Error, Equatable, CustomStringConvertible, LocalizedError {
|
|
38
48
|
public let code: WalletErrorCode
|
|
39
49
|
public let message: String
|
|
50
|
+
/// The server's request ID (`requestId` in the error body, else the `X-Request-Id` header)
|
|
51
|
+
/// when the error came from an API response; nil otherwise. Safe to log and to show support.
|
|
52
|
+
public let diagnosticId: String?
|
|
53
|
+
/// No response from the API (reported as API_ERROR, like the web frame).
|
|
54
|
+
let isNetworkFailure: Bool
|
|
40
55
|
|
|
41
|
-
public init(_ code: WalletErrorCode, _ message: String? = nil) {
|
|
56
|
+
public init(_ code: WalletErrorCode, _ message: String? = nil, diagnosticId: String? = nil) {
|
|
42
57
|
self.code = code
|
|
43
58
|
self.message = message ?? code.rawValue
|
|
59
|
+
self.diagnosticId = diagnosticId
|
|
60
|
+
isNetworkFailure = false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private init(networkFailure message: String) {
|
|
64
|
+
code = .apiError
|
|
65
|
+
self.message = message
|
|
66
|
+
diagnosticId = nil
|
|
67
|
+
isNetworkFailure = true
|
|
44
68
|
}
|
|
45
69
|
|
|
46
|
-
|
|
70
|
+
static func network() -> WalletError { WalletError(networkFailure: "network error") }
|
|
71
|
+
|
|
72
|
+
public var retryable: Bool { code.retryable }
|
|
73
|
+
|
|
74
|
+
public var description: String {
|
|
75
|
+
"WalletError(\(code.rawValue)): \(message)" + (diagnosticId.map { " [\($0)]" } ?? "")
|
|
76
|
+
}
|
|
47
77
|
public var errorDescription: String? { message }
|
|
48
78
|
|
|
49
79
|
public static func == (a: WalletError, b: WalletError) -> Bool { a.code == b.code }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# CKeccak
|
|
2
2
|
|
|
3
|
-
Keccak-256 (original Keccak padding, as used by Ethereum)
|
|
3
|
+
Keccak-256 (original Keccak padding, as used by Ethereum) and RIPEMD-160 (Bitcoin/XRP hash160)
|
|
4
|
+
for AuthonWallet.
|
|
4
5
|
|
|
5
6
|
Vendored unchanged from trezor-crypto, MIT (see LICENSE):
|
|
6
7
|
|
|
@@ -12,14 +13,16 @@ Vendored unchanged from trezor-crypto, MIT (see LICENSE):
|
|
|
12
13
|
| memzero.h | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/memzero.h | ffec031a236dde8df1c0b95cd0c3bd28ca046f6dc62faff36be8401ba82b214a |
|
|
13
14
|
| byte_order.h | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/byte_order.h | 496a5a80346a0fb48ef3fbf53c0da2b69399e1de224d67962342657a9dfd77d1 |
|
|
14
15
|
| options.h | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/options.h | 02884451075e84c7d9099a2fd295f1fcd87f7df0f3c7812ecba98b398ebe7a4e |
|
|
16
|
+
| ripemd160.c | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/ripemd160.c | cdb95bc4dc735063ea8d45d57d76ea0b81838693a7199b0772f0adb47b47b934 |
|
|
17
|
+
| ripemd160.h | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/ripemd160.h | e06d618b788918e52f37ceb0249f2752364e7932437d0b6972946213dba011fc |
|
|
15
18
|
| LICENSE | https://github.com/trezor/trezor-firmware/blob/core/v2.8.0/crypto/LICENSE | b53d2eb93806f3d618370726f27eafeb6c279c7a90351297f79e073e49e569be |
|
|
16
19
|
|
|
17
|
-
`include/ckeccak.h` is ours: it only declares `keccak_256` for Swift.
|
|
20
|
+
`include/ckeccak.h` is ours: it only declares `keccak_256` and `ripemd160` for Swift.
|
|
18
21
|
|
|
19
22
|
## Building outside SwiftPM (CocoaPods)
|
|
20
23
|
|
|
21
24
|
Self-contained; no defines or flags (`options.h` already sets `USE_KECCAK 1`) and no header search paths.
|
|
22
|
-
Compile `sha3.c` and `memzero.c`; the public header is `include/ckeccak.h`.
|
|
25
|
+
Compile `sha3.c`, `ripemd160.c` and `memzero.c`; the public header is `include/ckeccak.h`.
|
|
23
26
|
|
|
24
27
|
```ruby
|
|
25
28
|
s.source_files = 'CKeccak/*.{c,h}', 'CKeccak/include/ckeccak.h'
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
#define CKECCAK_H
|
|
3
3
|
|
|
4
4
|
#include <stddef.h>
|
|
5
|
+
#include <stdint.h>
|
|
5
6
|
|
|
6
7
|
/* Original Keccak-256 (Ethereum), implemented in ../sha3.c. */
|
|
7
8
|
void keccak_256(const unsigned char *data, size_t len, unsigned char *digest);
|
|
8
9
|
|
|
10
|
+
/* RIPEMD-160, implemented in ../ripemd160.c. */
|
|
11
|
+
void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[20]);
|
|
12
|
+
|
|
9
13
|
#endif
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* RIPE MD-160 implementation
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
8
|
+
* not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
15
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*
|
|
19
|
+
* This file is part of mbed TLS (https://tls.mbed.org)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* The RIPEMD-160 algorithm was designed by RIPE in 1996
|
|
24
|
+
* http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
|
25
|
+
* http://ehash.iaik.tugraz.at/wiki/RIPEMD-160
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
#include <string.h>
|
|
29
|
+
|
|
30
|
+
#include "ripemd160.h"
|
|
31
|
+
#include "memzero.h"
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* 32-bit integer manipulation macros (little endian)
|
|
35
|
+
*/
|
|
36
|
+
#ifndef GET_UINT32_LE
|
|
37
|
+
#define GET_UINT32_LE(n,b,i) \
|
|
38
|
+
{ \
|
|
39
|
+
(n) = ( (uint32_t) (b)[(i) ] ) \
|
|
40
|
+
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
|
|
41
|
+
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
|
|
42
|
+
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
|
|
43
|
+
}
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
#ifndef PUT_UINT32_LE
|
|
47
|
+
#define PUT_UINT32_LE(n,b,i) \
|
|
48
|
+
{ \
|
|
49
|
+
(b)[(i) ] = (uint8_t) ( ( (n) ) & 0xFF ); \
|
|
50
|
+
(b)[(i) + 1] = (uint8_t) ( ( (n) >> 8 ) & 0xFF ); \
|
|
51
|
+
(b)[(i) + 2] = (uint8_t) ( ( (n) >> 16 ) & 0xFF ); \
|
|
52
|
+
(b)[(i) + 3] = (uint8_t) ( ( (n) >> 24 ) & 0xFF ); \
|
|
53
|
+
}
|
|
54
|
+
#endif
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* RIPEMD-160 context setup
|
|
58
|
+
*/
|
|
59
|
+
void ripemd160_Init(RIPEMD160_CTX *ctx)
|
|
60
|
+
{
|
|
61
|
+
memzero(ctx, sizeof(RIPEMD160_CTX));
|
|
62
|
+
ctx->total[0] = 0;
|
|
63
|
+
ctx->total[1] = 0;
|
|
64
|
+
ctx->state[0] = 0x67452301;
|
|
65
|
+
ctx->state[1] = 0xEFCDAB89;
|
|
66
|
+
ctx->state[2] = 0x98BADCFE;
|
|
67
|
+
ctx->state[3] = 0x10325476;
|
|
68
|
+
ctx->state[4] = 0xC3D2E1F0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)
|
|
72
|
+
/*
|
|
73
|
+
* Process one block
|
|
74
|
+
*/
|
|
75
|
+
void ripemd160_process( RIPEMD160_CTX *ctx, const uint8_t data[RIPEMD160_BLOCK_LENGTH] )
|
|
76
|
+
{
|
|
77
|
+
uint32_t A = 0, B = 0, C = 0, D = 0, E = 0, Ap = 0, Bp = 0, Cp = 0, Dp = 0, Ep = 0, X[16] = {0};
|
|
78
|
+
|
|
79
|
+
GET_UINT32_LE( X[ 0], data, 0 );
|
|
80
|
+
GET_UINT32_LE( X[ 1], data, 4 );
|
|
81
|
+
GET_UINT32_LE( X[ 2], data, 8 );
|
|
82
|
+
GET_UINT32_LE( X[ 3], data, 12 );
|
|
83
|
+
GET_UINT32_LE( X[ 4], data, 16 );
|
|
84
|
+
GET_UINT32_LE( X[ 5], data, 20 );
|
|
85
|
+
GET_UINT32_LE( X[ 6], data, 24 );
|
|
86
|
+
GET_UINT32_LE( X[ 7], data, 28 );
|
|
87
|
+
GET_UINT32_LE( X[ 8], data, 32 );
|
|
88
|
+
GET_UINT32_LE( X[ 9], data, 36 );
|
|
89
|
+
GET_UINT32_LE( X[10], data, 40 );
|
|
90
|
+
GET_UINT32_LE( X[11], data, 44 );
|
|
91
|
+
GET_UINT32_LE( X[12], data, 48 );
|
|
92
|
+
GET_UINT32_LE( X[13], data, 52 );
|
|
93
|
+
GET_UINT32_LE( X[14], data, 56 );
|
|
94
|
+
GET_UINT32_LE( X[15], data, 60 );
|
|
95
|
+
|
|
96
|
+
A = Ap = ctx->state[0];
|
|
97
|
+
B = Bp = ctx->state[1];
|
|
98
|
+
C = Cp = ctx->state[2];
|
|
99
|
+
D = Dp = ctx->state[3];
|
|
100
|
+
E = Ep = ctx->state[4];
|
|
101
|
+
|
|
102
|
+
#define F1( x, y, z ) ( x ^ y ^ z )
|
|
103
|
+
#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) )
|
|
104
|
+
#define F3( x, y, z ) ( ( x | ~y ) ^ z )
|
|
105
|
+
#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) )
|
|
106
|
+
#define F5( x, y, z ) ( x ^ ( y | ~z ) )
|
|
107
|
+
|
|
108
|
+
#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) )
|
|
109
|
+
|
|
110
|
+
#define P( a, b, c, d, e, r, s, f, k ) \
|
|
111
|
+
a += f( b, c, d ) + X[r] + k; \
|
|
112
|
+
a = S( a, s ) + e; \
|
|
113
|
+
c = S( c, 10 );
|
|
114
|
+
|
|
115
|
+
#define P2( a, b, c, d, e, r, s, rp, sp ) \
|
|
116
|
+
P( a, b, c, d, e, r, s, F, K ); \
|
|
117
|
+
P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp );
|
|
118
|
+
|
|
119
|
+
#define F F1
|
|
120
|
+
#define K 0x00000000
|
|
121
|
+
#define Fp F5
|
|
122
|
+
#define Kp 0x50A28BE6
|
|
123
|
+
P2( A, B, C, D, E, 0, 11, 5, 8 );
|
|
124
|
+
P2( E, A, B, C, D, 1, 14, 14, 9 );
|
|
125
|
+
P2( D, E, A, B, C, 2, 15, 7, 9 );
|
|
126
|
+
P2( C, D, E, A, B, 3, 12, 0, 11 );
|
|
127
|
+
P2( B, C, D, E, A, 4, 5, 9, 13 );
|
|
128
|
+
P2( A, B, C, D, E, 5, 8, 2, 15 );
|
|
129
|
+
P2( E, A, B, C, D, 6, 7, 11, 15 );
|
|
130
|
+
P2( D, E, A, B, C, 7, 9, 4, 5 );
|
|
131
|
+
P2( C, D, E, A, B, 8, 11, 13, 7 );
|
|
132
|
+
P2( B, C, D, E, A, 9, 13, 6, 7 );
|
|
133
|
+
P2( A, B, C, D, E, 10, 14, 15, 8 );
|
|
134
|
+
P2( E, A, B, C, D, 11, 15, 8, 11 );
|
|
135
|
+
P2( D, E, A, B, C, 12, 6, 1, 14 );
|
|
136
|
+
P2( C, D, E, A, B, 13, 7, 10, 14 );
|
|
137
|
+
P2( B, C, D, E, A, 14, 9, 3, 12 );
|
|
138
|
+
P2( A, B, C, D, E, 15, 8, 12, 6 );
|
|
139
|
+
#undef F
|
|
140
|
+
#undef K
|
|
141
|
+
#undef Fp
|
|
142
|
+
#undef Kp
|
|
143
|
+
|
|
144
|
+
#define F F2
|
|
145
|
+
#define K 0x5A827999
|
|
146
|
+
#define Fp F4
|
|
147
|
+
#define Kp 0x5C4DD124
|
|
148
|
+
P2( E, A, B, C, D, 7, 7, 6, 9 );
|
|
149
|
+
P2( D, E, A, B, C, 4, 6, 11, 13 );
|
|
150
|
+
P2( C, D, E, A, B, 13, 8, 3, 15 );
|
|
151
|
+
P2( B, C, D, E, A, 1, 13, 7, 7 );
|
|
152
|
+
P2( A, B, C, D, E, 10, 11, 0, 12 );
|
|
153
|
+
P2( E, A, B, C, D, 6, 9, 13, 8 );
|
|
154
|
+
P2( D, E, A, B, C, 15, 7, 5, 9 );
|
|
155
|
+
P2( C, D, E, A, B, 3, 15, 10, 11 );
|
|
156
|
+
P2( B, C, D, E, A, 12, 7, 14, 7 );
|
|
157
|
+
P2( A, B, C, D, E, 0, 12, 15, 7 );
|
|
158
|
+
P2( E, A, B, C, D, 9, 15, 8, 12 );
|
|
159
|
+
P2( D, E, A, B, C, 5, 9, 12, 7 );
|
|
160
|
+
P2( C, D, E, A, B, 2, 11, 4, 6 );
|
|
161
|
+
P2( B, C, D, E, A, 14, 7, 9, 15 );
|
|
162
|
+
P2( A, B, C, D, E, 11, 13, 1, 13 );
|
|
163
|
+
P2( E, A, B, C, D, 8, 12, 2, 11 );
|
|
164
|
+
#undef F
|
|
165
|
+
#undef K
|
|
166
|
+
#undef Fp
|
|
167
|
+
#undef Kp
|
|
168
|
+
|
|
169
|
+
#define F F3
|
|
170
|
+
#define K 0x6ED9EBA1
|
|
171
|
+
#define Fp F3
|
|
172
|
+
#define Kp 0x6D703EF3
|
|
173
|
+
P2( D, E, A, B, C, 3, 11, 15, 9 );
|
|
174
|
+
P2( C, D, E, A, B, 10, 13, 5, 7 );
|
|
175
|
+
P2( B, C, D, E, A, 14, 6, 1, 15 );
|
|
176
|
+
P2( A, B, C, D, E, 4, 7, 3, 11 );
|
|
177
|
+
P2( E, A, B, C, D, 9, 14, 7, 8 );
|
|
178
|
+
P2( D, E, A, B, C, 15, 9, 14, 6 );
|
|
179
|
+
P2( C, D, E, A, B, 8, 13, 6, 6 );
|
|
180
|
+
P2( B, C, D, E, A, 1, 15, 9, 14 );
|
|
181
|
+
P2( A, B, C, D, E, 2, 14, 11, 12 );
|
|
182
|
+
P2( E, A, B, C, D, 7, 8, 8, 13 );
|
|
183
|
+
P2( D, E, A, B, C, 0, 13, 12, 5 );
|
|
184
|
+
P2( C, D, E, A, B, 6, 6, 2, 14 );
|
|
185
|
+
P2( B, C, D, E, A, 13, 5, 10, 13 );
|
|
186
|
+
P2( A, B, C, D, E, 11, 12, 0, 13 );
|
|
187
|
+
P2( E, A, B, C, D, 5, 7, 4, 7 );
|
|
188
|
+
P2( D, E, A, B, C, 12, 5, 13, 5 );
|
|
189
|
+
#undef F
|
|
190
|
+
#undef K
|
|
191
|
+
#undef Fp
|
|
192
|
+
#undef Kp
|
|
193
|
+
|
|
194
|
+
#define F F4
|
|
195
|
+
#define K 0x8F1BBCDC
|
|
196
|
+
#define Fp F2
|
|
197
|
+
#define Kp 0x7A6D76E9
|
|
198
|
+
P2( C, D, E, A, B, 1, 11, 8, 15 );
|
|
199
|
+
P2( B, C, D, E, A, 9, 12, 6, 5 );
|
|
200
|
+
P2( A, B, C, D, E, 11, 14, 4, 8 );
|
|
201
|
+
P2( E, A, B, C, D, 10, 15, 1, 11 );
|
|
202
|
+
P2( D, E, A, B, C, 0, 14, 3, 14 );
|
|
203
|
+
P2( C, D, E, A, B, 8, 15, 11, 14 );
|
|
204
|
+
P2( B, C, D, E, A, 12, 9, 15, 6 );
|
|
205
|
+
P2( A, B, C, D, E, 4, 8, 0, 14 );
|
|
206
|
+
P2( E, A, B, C, D, 13, 9, 5, 6 );
|
|
207
|
+
P2( D, E, A, B, C, 3, 14, 12, 9 );
|
|
208
|
+
P2( C, D, E, A, B, 7, 5, 2, 12 );
|
|
209
|
+
P2( B, C, D, E, A, 15, 6, 13, 9 );
|
|
210
|
+
P2( A, B, C, D, E, 14, 8, 9, 12 );
|
|
211
|
+
P2( E, A, B, C, D, 5, 6, 7, 5 );
|
|
212
|
+
P2( D, E, A, B, C, 6, 5, 10, 15 );
|
|
213
|
+
P2( C, D, E, A, B, 2, 12, 14, 8 );
|
|
214
|
+
#undef F
|
|
215
|
+
#undef K
|
|
216
|
+
#undef Fp
|
|
217
|
+
#undef Kp
|
|
218
|
+
|
|
219
|
+
#define F F5
|
|
220
|
+
#define K 0xA953FD4E
|
|
221
|
+
#define Fp F1
|
|
222
|
+
#define Kp 0x00000000
|
|
223
|
+
P2( B, C, D, E, A, 4, 9, 12, 8 );
|
|
224
|
+
P2( A, B, C, D, E, 0, 15, 15, 5 );
|
|
225
|
+
P2( E, A, B, C, D, 5, 5, 10, 12 );
|
|
226
|
+
P2( D, E, A, B, C, 9, 11, 4, 9 );
|
|
227
|
+
P2( C, D, E, A, B, 7, 6, 1, 12 );
|
|
228
|
+
P2( B, C, D, E, A, 12, 8, 5, 5 );
|
|
229
|
+
P2( A, B, C, D, E, 2, 13, 8, 14 );
|
|
230
|
+
P2( E, A, B, C, D, 10, 12, 7, 6 );
|
|
231
|
+
P2( D, E, A, B, C, 14, 5, 6, 8 );
|
|
232
|
+
P2( C, D, E, A, B, 1, 12, 2, 13 );
|
|
233
|
+
P2( B, C, D, E, A, 3, 13, 13, 6 );
|
|
234
|
+
P2( A, B, C, D, E, 8, 14, 14, 5 );
|
|
235
|
+
P2( E, A, B, C, D, 11, 11, 0, 15 );
|
|
236
|
+
P2( D, E, A, B, C, 6, 8, 3, 13 );
|
|
237
|
+
P2( C, D, E, A, B, 15, 5, 9, 11 );
|
|
238
|
+
P2( B, C, D, E, A, 13, 6, 11, 11 );
|
|
239
|
+
#undef F
|
|
240
|
+
#undef K
|
|
241
|
+
#undef Fp
|
|
242
|
+
#undef Kp
|
|
243
|
+
|
|
244
|
+
C = ctx->state[1] + C + Dp;
|
|
245
|
+
ctx->state[1] = ctx->state[2] + D + Ep;
|
|
246
|
+
ctx->state[2] = ctx->state[3] + E + Ap;
|
|
247
|
+
ctx->state[3] = ctx->state[4] + A + Bp;
|
|
248
|
+
ctx->state[4] = ctx->state[0] + B + Cp;
|
|
249
|
+
ctx->state[0] = C;
|
|
250
|
+
}
|
|
251
|
+
#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
* RIPEMD-160 process buffer
|
|
255
|
+
*/
|
|
256
|
+
void ripemd160_Update( RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen )
|
|
257
|
+
{
|
|
258
|
+
uint32_t fill = 0;
|
|
259
|
+
uint32_t left = 0;
|
|
260
|
+
|
|
261
|
+
if( ilen == 0 )
|
|
262
|
+
return;
|
|
263
|
+
|
|
264
|
+
left = ctx->total[0] & 0x3F;
|
|
265
|
+
fill = RIPEMD160_BLOCK_LENGTH - left;
|
|
266
|
+
|
|
267
|
+
ctx->total[0] += (uint32_t) ilen;
|
|
268
|
+
ctx->total[0] &= 0xFFFFFFFF;
|
|
269
|
+
|
|
270
|
+
if( ctx->total[0] < (uint32_t) ilen )
|
|
271
|
+
ctx->total[1]++;
|
|
272
|
+
|
|
273
|
+
if( left && ilen >= fill )
|
|
274
|
+
{
|
|
275
|
+
memcpy( (void *) (ctx->buffer + left), input, fill );
|
|
276
|
+
ripemd160_process( ctx, ctx->buffer );
|
|
277
|
+
input += fill;
|
|
278
|
+
ilen -= fill;
|
|
279
|
+
left = 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
while( ilen >= RIPEMD160_BLOCK_LENGTH )
|
|
283
|
+
{
|
|
284
|
+
ripemd160_process( ctx, input );
|
|
285
|
+
input += RIPEMD160_BLOCK_LENGTH;
|
|
286
|
+
ilen -= RIPEMD160_BLOCK_LENGTH;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if( ilen > 0 )
|
|
290
|
+
{
|
|
291
|
+
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static const uint8_t ripemd160_padding[RIPEMD160_BLOCK_LENGTH] =
|
|
296
|
+
{
|
|
297
|
+
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
298
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
299
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
300
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
* RIPEMD-160 final digest
|
|
305
|
+
*/
|
|
306
|
+
void ripemd160_Final( RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH] )
|
|
307
|
+
{
|
|
308
|
+
uint32_t last = 0; uint32_t padn = 0;
|
|
309
|
+
uint32_t high = 0; uint32_t low = 0;
|
|
310
|
+
uint8_t msglen[8] = {0};
|
|
311
|
+
|
|
312
|
+
high = ( ctx->total[0] >> 29 )
|
|
313
|
+
| ( ctx->total[1] << 3 );
|
|
314
|
+
low = ( ctx->total[0] << 3 );
|
|
315
|
+
|
|
316
|
+
PUT_UINT32_LE( low, msglen, 0 );
|
|
317
|
+
PUT_UINT32_LE( high, msglen, 4 );
|
|
318
|
+
|
|
319
|
+
last = ctx->total[0] & 0x3F;
|
|
320
|
+
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
|
321
|
+
|
|
322
|
+
ripemd160_Update( ctx, ripemd160_padding, padn );
|
|
323
|
+
ripemd160_Update( ctx, msglen, 8 );
|
|
324
|
+
|
|
325
|
+
PUT_UINT32_LE( ctx->state[0], output, 0 );
|
|
326
|
+
PUT_UINT32_LE( ctx->state[1], output, 4 );
|
|
327
|
+
PUT_UINT32_LE( ctx->state[2], output, 8 );
|
|
328
|
+
PUT_UINT32_LE( ctx->state[3], output, 12 );
|
|
329
|
+
PUT_UINT32_LE( ctx->state[4], output, 16 );
|
|
330
|
+
|
|
331
|
+
memzero(ctx, sizeof(RIPEMD160_CTX));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/*
|
|
335
|
+
* output = RIPEMD-160( input buffer )
|
|
336
|
+
*/
|
|
337
|
+
void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH])
|
|
338
|
+
{
|
|
339
|
+
RIPEMD160_CTX ctx = {0};
|
|
340
|
+
ripemd160_Init( &ctx );
|
|
341
|
+
ripemd160_Update( &ctx, msg, msg_len );
|
|
342
|
+
ripemd160_Final( &ctx, hash );
|
|
343
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#ifndef __RIPEMD160_H__
|
|
2
|
+
#define __RIPEMD160_H__
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
|
|
6
|
+
#define RIPEMD160_BLOCK_LENGTH 64
|
|
7
|
+
#define RIPEMD160_DIGEST_LENGTH 20
|
|
8
|
+
|
|
9
|
+
typedef struct _RIPEMD160_CTX {
|
|
10
|
+
uint32_t total[2]; /*!< number of bytes processed */
|
|
11
|
+
uint32_t state[5]; /*!< intermediate digest state */
|
|
12
|
+
uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */
|
|
13
|
+
} RIPEMD160_CTX;
|
|
14
|
+
|
|
15
|
+
void ripemd160_Init(RIPEMD160_CTX *ctx);
|
|
16
|
+
void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen);
|
|
17
|
+
void ripemd160_Final(RIPEMD160_CTX *ctx,
|
|
18
|
+
uint8_t output[RIPEMD160_DIGEST_LENGTH]);
|
|
19
|
+
void ripemd160(const uint8_t *msg, uint32_t msg_len,
|
|
20
|
+
uint8_t hash[RIPEMD160_DIGEST_LENGTH]);
|
|
21
|
+
|
|
22
|
+
#endif
|