@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +34 -4
  3. package/android/src/main/AndroidManifest.xml +4 -0
  4. package/android/src/main/java/dev/authon/reactnative/wallet/AuthonWalletModule.kt +57 -3
  5. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/AndroidCapabilityProbe.kt +86 -0
  6. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/AuthonWallet.kt +29 -2
  7. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Bitcoin.kt +296 -0
  8. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Chains.kt +157 -0
  9. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Der.kt +17 -0
  10. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Encodings.kt +133 -0
  11. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Http.kt +6 -2
  12. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/KeystoreDeviceStore.kt +27 -23
  13. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Solana.kt +195 -0
  14. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Tron.kt +184 -0
  15. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletApi.kt +16 -8
  16. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletCapabilities.kt +91 -0
  17. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletError.kt +18 -2
  18. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletOps.kt +103 -1
  19. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/WalletTypes.kt +8 -1
  20. package/android/src/vendor/kotlin/dev/authon/sdk/wallet/Xrp.kt +193 -0
  21. package/build/client.d.ts +18 -2
  22. package/build/client.d.ts.map +1 -1
  23. package/build/client.js +88 -6
  24. package/build/client.js.map +1 -1
  25. package/build/errors.d.ts +8 -1
  26. package/build/errors.d.ts.map +1 -1
  27. package/build/errors.js +7 -1
  28. package/build/errors.js.map +1 -1
  29. package/build/index.d.ts +1 -1
  30. package/build/index.d.ts.map +1 -1
  31. package/build/native.d.ts +5 -1
  32. package/build/native.d.ts.map +1 -1
  33. package/build/native.js.map +1 -1
  34. package/build/types.d.ts +47 -1
  35. package/build/types.d.ts.map +1 -1
  36. package/ios/AuthonReactNativeWallet.podspec +6 -2
  37. package/ios/AuthonWalletModule.swift +46 -3
  38. package/ios/vendor/AuthonWallet/AuthonWallet.swift +24 -4
  39. package/ios/vendor/AuthonWallet/Capabilities.swift +149 -0
  40. package/ios/vendor/AuthonWallet/Chains/Bitcoin.swift +296 -0
  41. package/ios/vendor/AuthonWallet/Chains/Solana.swift +207 -0
  42. package/ios/vendor/AuthonWallet/Chains/Tron.swift +181 -0
  43. package/ios/vendor/AuthonWallet/Chains/XRP.swift +191 -0
  44. package/ios/vendor/AuthonWallet/Crypto/Chains.swift +278 -0
  45. package/ios/vendor/AuthonWallet/Crypto/Secp256k1.swift +24 -0
  46. package/ios/vendor/AuthonWallet/Wallet/WalletAPI.swift +19 -8
  47. package/ios/vendor/AuthonWallet/Wallet/WalletOps.swift +101 -2
  48. package/ios/vendor/AuthonWallet/WalletError.swift +32 -2
  49. package/ios/vendor/CKeccak/README.md +6 -3
  50. package/ios/vendor/CKeccak/include/ckeccak.h +4 -0
  51. package/ios/vendor/CKeccak/ripemd160.c +343 -0
  52. package/ios/vendor/CKeccak/ripemd160.h +22 -0
  53. package/ios/vendor/CMonocypher/LICENCE.md +173 -0
  54. package/ios/vendor/CMonocypher/README.md +27 -0
  55. package/ios/vendor/CMonocypher/include/monocypher-ed25519.h +140 -0
  56. package/ios/vendor/CMonocypher/include/monocypher.h +321 -0
  57. package/ios/vendor/CMonocypher/monocypher-ed25519.c +500 -0
  58. package/ios/vendor/CMonocypher/monocypher.c +2956 -0
  59. package/ios/vendor/GENERATED.md +1 -1
  60. package/package.json +3 -2
  61. package/src/client.ts +90 -6
  62. package/src/errors.ts +7 -1
  63. package/src/index.ts +5 -0
  64. package/src/native.ts +4 -2
  65. 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
- public var description: String { "WalletError(\(code.rawValue)): \(message)" }
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) for AuthonWallet.
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