@ecency/hive-tx 7.1.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/LICENSE +21 -0
- package/README.md +206 -0
- package/dist/browser/hive-tx.min.js +3 -0
- package/dist/browser/hive-tx.min.js.LICENSE.txt +5 -0
- package/dist/browser/hive-tx.min.js.map +1 -0
- package/dist/cjs/Transaction.d.ts +71 -0
- package/dist/cjs/Transaction.d.ts.map +1 -0
- package/dist/cjs/Transaction.js +199 -0
- package/dist/cjs/Transaction.js.map +1 -0
- package/dist/cjs/config.d.ts +37 -0
- package/dist/cjs/config.d.ts.map +1 -0
- package/dist/cjs/config.js +54 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/helpers/Asset.d.ts +21 -0
- package/dist/cjs/helpers/Asset.d.ts.map +1 -0
- package/dist/cjs/helpers/Asset.js +74 -0
- package/dist/cjs/helpers/Asset.js.map +1 -0
- package/dist/cjs/helpers/ByteBuffer.d.ts +75 -0
- package/dist/cjs/helpers/ByteBuffer.d.ts.map +1 -0
- package/dist/cjs/helpers/ByteBuffer.js +555 -0
- package/dist/cjs/helpers/ByteBuffer.js.map +1 -0
- package/dist/cjs/helpers/HexBuffer.d.ts +10 -0
- package/dist/cjs/helpers/HexBuffer.d.ts.map +1 -0
- package/dist/cjs/helpers/HexBuffer.js +33 -0
- package/dist/cjs/helpers/HexBuffer.js.map +1 -0
- package/dist/cjs/helpers/PrivateKey.d.ts +114 -0
- package/dist/cjs/helpers/PrivateKey.d.ts.map +1 -0
- package/dist/cjs/helpers/PrivateKey.js +212 -0
- package/dist/cjs/helpers/PrivateKey.js.map +1 -0
- package/dist/cjs/helpers/PublicKey.d.ts +47 -0
- package/dist/cjs/helpers/PublicKey.d.ts.map +1 -0
- package/dist/cjs/helpers/PublicKey.js +97 -0
- package/dist/cjs/helpers/PublicKey.js.map +1 -0
- package/dist/cjs/helpers/Signature.d.ts +38 -0
- package/dist/cjs/helpers/Signature.d.ts.map +1 -0
- package/dist/cjs/helpers/Signature.js +85 -0
- package/dist/cjs/helpers/Signature.js.map +1 -0
- package/dist/cjs/helpers/aes.d.ts +15 -0
- package/dist/cjs/helpers/aes.d.ts.map +1 -0
- package/dist/cjs/helpers/aes.js +87 -0
- package/dist/cjs/helpers/aes.js.map +1 -0
- package/dist/cjs/helpers/call.d.ts +119 -0
- package/dist/cjs/helpers/call.d.ts.map +1 -0
- package/dist/cjs/helpers/call.js +498 -0
- package/dist/cjs/helpers/call.js.map +1 -0
- package/dist/cjs/helpers/deserializer.d.ts +4 -0
- package/dist/cjs/helpers/deserializer.d.ts.map +1 -0
- package/dist/cjs/helpers/deserializer.js +58 -0
- package/dist/cjs/helpers/deserializer.js.map +1 -0
- package/dist/cjs/helpers/memo.d.ts +36 -0
- package/dist/cjs/helpers/memo.d.ts.map +1 -0
- package/dist/cjs/helpers/memo.js +167 -0
- package/dist/cjs/helpers/memo.js.map +1 -0
- package/dist/cjs/helpers/serializer.d.ts +14 -0
- package/dist/cjs/helpers/serializer.d.ts.map +1 -0
- package/dist/cjs/helpers/serializer.js +639 -0
- package/dist/cjs/helpers/serializer.js.map +1 -0
- package/dist/cjs/helpers/sleep.d.ts +2 -0
- package/dist/cjs/helpers/sleep.d.ts.map +1 -0
- package/dist/cjs/helpers/sleep.js +8 -0
- package/dist/cjs/helpers/sleep.js.map +1 -0
- package/dist/cjs/helpers/utils.d.ts +122 -0
- package/dist/cjs/helpers/utils.d.ts.map +1 -0
- package/dist/cjs/helpers/utils.js +202 -0
- package/dist/cjs/helpers/utils.js.map +1 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +60 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/type_generators/types/balance.d.ts +1096 -0
- package/dist/cjs/type_generators/types/balance.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/balance.js +3 -0
- package/dist/cjs/type_generators/types/balance.js.map +1 -0
- package/dist/cjs/type_generators/types/hafah.d.ts +2154 -0
- package/dist/cjs/type_generators/types/hafah.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/hafah.js +3 -0
- package/dist/cjs/type_generators/types/hafah.js.map +1 -0
- package/dist/cjs/type_generators/types/hafbe.d.ts +2121 -0
- package/dist/cjs/type_generators/types/hafbe.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/hafbe.js +3 -0
- package/dist/cjs/type_generators/types/hafbe.js.map +1 -0
- package/dist/cjs/type_generators/types/hafsql.d.ts +2439 -0
- package/dist/cjs/type_generators/types/hafsql.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/hafsql.js +3 -0
- package/dist/cjs/type_generators/types/hafsql.js.map +1 -0
- package/dist/cjs/type_generators/types/hivemind.d.ts +202 -0
- package/dist/cjs/type_generators/types/hivemind.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/hivemind.js +3 -0
- package/dist/cjs/type_generators/types/hivemind.js.map +1 -0
- package/dist/cjs/type_generators/types/hivesense.d.ts +448 -0
- package/dist/cjs/type_generators/types/hivesense.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/hivesense.js +3 -0
- package/dist/cjs/type_generators/types/hivesense.js.map +1 -0
- package/dist/cjs/type_generators/types/nft-tracker.d.ts +348 -0
- package/dist/cjs/type_generators/types/nft-tracker.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/nft-tracker.js +3 -0
- package/dist/cjs/type_generators/types/nft-tracker.js.map +1 -0
- package/dist/cjs/type_generators/types/reputation.d.ts +182 -0
- package/dist/cjs/type_generators/types/reputation.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/reputation.js +3 -0
- package/dist/cjs/type_generators/types/reputation.js.map +1 -0
- package/dist/cjs/type_generators/types/status.d.ts +139 -0
- package/dist/cjs/type_generators/types/status.d.ts.map +1 -0
- package/dist/cjs/type_generators/types/status.js +3 -0
- package/dist/cjs/type_generators/types/status.js.map +1 -0
- package/dist/cjs/types.d.ts +415 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/Transaction.d.ts +71 -0
- package/dist/esm/Transaction.d.ts.map +1 -0
- package/dist/esm/Transaction.js +195 -0
- package/dist/esm/Transaction.js.map +1 -0
- package/dist/esm/config.d.ts +37 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +51 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/helpers/Asset.d.ts +21 -0
- package/dist/esm/helpers/Asset.d.ts.map +1 -0
- package/dist/esm/helpers/Asset.js +70 -0
- package/dist/esm/helpers/Asset.js.map +1 -0
- package/dist/esm/helpers/ByteBuffer.d.ts +75 -0
- package/dist/esm/helpers/ByteBuffer.d.ts.map +1 -0
- package/dist/esm/helpers/ByteBuffer.js +551 -0
- package/dist/esm/helpers/ByteBuffer.js.map +1 -0
- package/dist/esm/helpers/HexBuffer.d.ts +10 -0
- package/dist/esm/helpers/HexBuffer.d.ts.map +1 -0
- package/dist/esm/helpers/HexBuffer.js +29 -0
- package/dist/esm/helpers/HexBuffer.js.map +1 -0
- package/dist/esm/helpers/PrivateKey.d.ts +114 -0
- package/dist/esm/helpers/PrivateKey.d.ts.map +1 -0
- package/dist/esm/helpers/PrivateKey.js +205 -0
- package/dist/esm/helpers/PrivateKey.js.map +1 -0
- package/dist/esm/helpers/PublicKey.d.ts +47 -0
- package/dist/esm/helpers/PublicKey.d.ts.map +1 -0
- package/dist/esm/helpers/PublicKey.js +90 -0
- package/dist/esm/helpers/PublicKey.js.map +1 -0
- package/dist/esm/helpers/Signature.d.ts +38 -0
- package/dist/esm/helpers/Signature.d.ts.map +1 -0
- package/dist/esm/helpers/Signature.js +81 -0
- package/dist/esm/helpers/Signature.js.map +1 -0
- package/dist/esm/helpers/aes.d.ts +15 -0
- package/dist/esm/helpers/aes.d.ts.map +1 -0
- package/dist/esm/helpers/aes.js +81 -0
- package/dist/esm/helpers/aes.js.map +1 -0
- package/dist/esm/helpers/call.d.ts +119 -0
- package/dist/esm/helpers/call.d.ts.map +1 -0
- package/dist/esm/helpers/call.js +490 -0
- package/dist/esm/helpers/call.js.map +1 -0
- package/dist/esm/helpers/deserializer.d.ts +4 -0
- package/dist/esm/helpers/deserializer.d.ts.map +1 -0
- package/dist/esm/helpers/deserializer.js +55 -0
- package/dist/esm/helpers/deserializer.js.map +1 -0
- package/dist/esm/helpers/memo.d.ts +36 -0
- package/dist/esm/helpers/memo.d.ts.map +1 -0
- package/dist/esm/helpers/memo.js +128 -0
- package/dist/esm/helpers/memo.js.map +1 -0
- package/dist/esm/helpers/serializer.d.ts +14 -0
- package/dist/esm/helpers/serializer.d.ts.map +1 -0
- package/dist/esm/helpers/serializer.js +636 -0
- package/dist/esm/helpers/serializer.js.map +1 -0
- package/dist/esm/helpers/sleep.d.ts +2 -0
- package/dist/esm/helpers/sleep.d.ts.map +1 -0
- package/dist/esm/helpers/sleep.js +4 -0
- package/dist/esm/helpers/sleep.js.map +1 -0
- package/dist/esm/helpers/utils.d.ts +122 -0
- package/dist/esm/helpers/utils.d.ts.map +1 -0
- package/dist/esm/helpers/utils.js +196 -0
- package/dist/esm/helpers/utils.js.map +1 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/type_generators/types/balance.d.ts +1096 -0
- package/dist/esm/type_generators/types/balance.d.ts.map +1 -0
- package/dist/esm/type_generators/types/balance.js +2 -0
- package/dist/esm/type_generators/types/balance.js.map +1 -0
- package/dist/esm/type_generators/types/hafah.d.ts +2154 -0
- package/dist/esm/type_generators/types/hafah.d.ts.map +1 -0
- package/dist/esm/type_generators/types/hafah.js +2 -0
- package/dist/esm/type_generators/types/hafah.js.map +1 -0
- package/dist/esm/type_generators/types/hafbe.d.ts +2121 -0
- package/dist/esm/type_generators/types/hafbe.d.ts.map +1 -0
- package/dist/esm/type_generators/types/hafbe.js +2 -0
- package/dist/esm/type_generators/types/hafbe.js.map +1 -0
- package/dist/esm/type_generators/types/hafsql.d.ts +2439 -0
- package/dist/esm/type_generators/types/hafsql.d.ts.map +1 -0
- package/dist/esm/type_generators/types/hafsql.js +2 -0
- package/dist/esm/type_generators/types/hafsql.js.map +1 -0
- package/dist/esm/type_generators/types/hivemind.d.ts +202 -0
- package/dist/esm/type_generators/types/hivemind.d.ts.map +1 -0
- package/dist/esm/type_generators/types/hivemind.js +2 -0
- package/dist/esm/type_generators/types/hivemind.js.map +1 -0
- package/dist/esm/type_generators/types/hivesense.d.ts +448 -0
- package/dist/esm/type_generators/types/hivesense.d.ts.map +1 -0
- package/dist/esm/type_generators/types/hivesense.js +2 -0
- package/dist/esm/type_generators/types/hivesense.js.map +1 -0
- package/dist/esm/type_generators/types/nft-tracker.d.ts +348 -0
- package/dist/esm/type_generators/types/nft-tracker.d.ts.map +1 -0
- package/dist/esm/type_generators/types/nft-tracker.js +2 -0
- package/dist/esm/type_generators/types/nft-tracker.js.map +1 -0
- package/dist/esm/type_generators/types/reputation.d.ts +182 -0
- package/dist/esm/type_generators/types/reputation.d.ts.map +1 -0
- package/dist/esm/type_generators/types/reputation.js +2 -0
- package/dist/esm/type_generators/types/reputation.js.map +1 -0
- package/dist/esm/type_generators/types/status.d.ts +139 -0
- package/dist/esm/type_generators/types/status.d.ts.map +1 -0
- package/dist/esm/type_generators/types/status.js +2 -0
- package/dist/esm/type_generators/types/status.js.map +1 -0
- package/dist/esm/types.d.ts +415 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { PublicKey } from './PublicKey';
|
|
2
|
+
import { Signature } from './Signature';
|
|
3
|
+
export type KeyRole = 'owner' | 'active' | 'posting' | 'memo';
|
|
4
|
+
/**
|
|
5
|
+
* ECDSA (secp256k1) private key for signing and encryption operations.
|
|
6
|
+
* Handles key generation, derivation from seeds/passwords, and cryptographic operations.
|
|
7
|
+
*
|
|
8
|
+
* All private keys are stored internally as Uint8Array and can be converted to/from
|
|
9
|
+
* Wallet Import Format (WIF) strings for storage and transmission.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // From WIF string
|
|
14
|
+
* const key = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')
|
|
15
|
+
*
|
|
16
|
+
* // Generate random key
|
|
17
|
+
* const randomKey = PrivateKey.randomKey()
|
|
18
|
+
*
|
|
19
|
+
* // From username and password
|
|
20
|
+
* const loginKey = PrivateKey.fromLogin('username', 'password')
|
|
21
|
+
*
|
|
22
|
+
* // Sign a message
|
|
23
|
+
* const signature = key.sign(someHash)
|
|
24
|
+
*
|
|
25
|
+
* // Get public key
|
|
26
|
+
* const pubKey = key.createPublic()
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class PrivateKey {
|
|
30
|
+
key: Uint8Array;
|
|
31
|
+
constructor(key: Uint8Array);
|
|
32
|
+
/**
|
|
33
|
+
* Creates a PrivateKey instance from a WIF string or raw Uint8Array.
|
|
34
|
+
* Automatically detects the input type and uses the appropriate method.
|
|
35
|
+
*
|
|
36
|
+
* @param value - WIF formatted string or raw 32-byte key as Uint8Array
|
|
37
|
+
* @returns New PrivateKey instance
|
|
38
|
+
* @throws Error if the key format is invalid
|
|
39
|
+
*/
|
|
40
|
+
static from(value: string | Uint8Array): PrivateKey;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a PrivateKey from a Wallet Import Format (WIF) encoded string.
|
|
43
|
+
*
|
|
44
|
+
* @param wif - WIF encoded private key string
|
|
45
|
+
* @returns New PrivateKey instance
|
|
46
|
+
* @throws Error if WIF format is invalid or checksum fails
|
|
47
|
+
*/
|
|
48
|
+
static fromString(wif: string): PrivateKey;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a PrivateKey from a seed string or Uint8Array.
|
|
51
|
+
* The seed is hashed with SHA256 to produce the private key.
|
|
52
|
+
*
|
|
53
|
+
* @param seed - Seed string (converted to bytes) or raw byte array
|
|
54
|
+
* @returns New PrivateKey instance derived from seed
|
|
55
|
+
*/
|
|
56
|
+
static fromSeed(seed: string | Uint8Array): PrivateKey;
|
|
57
|
+
/**
|
|
58
|
+
* Derives a PrivateKey from username, password, and role using Hive's key derivation scheme.
|
|
59
|
+
* This generates the same keys that the Hive wallet uses for login-based keys.
|
|
60
|
+
*
|
|
61
|
+
* @param username - Hive username
|
|
62
|
+
* @param password - Master password (or seed phrase)
|
|
63
|
+
* @param role - Key role ('owner', 'active', 'posting', 'memo')
|
|
64
|
+
* @returns New PrivateKey instance for the specified role
|
|
65
|
+
*/
|
|
66
|
+
static fromLogin(username: string, password: string, role?: KeyRole): PrivateKey;
|
|
67
|
+
/**
|
|
68
|
+
* Signs a 32-byte message hash using ECDSA and returns a recoverable signature.
|
|
69
|
+
* The signature includes recovery information to allow public key recovery.
|
|
70
|
+
*
|
|
71
|
+
* @param message - 32-byte message hash to sign (Uint8Array)
|
|
72
|
+
* @returns Signature object containing the signature data
|
|
73
|
+
*/
|
|
74
|
+
sign(message: Uint8Array): Signature;
|
|
75
|
+
/**
|
|
76
|
+
* Derives the corresponding public key for this private key.
|
|
77
|
+
*
|
|
78
|
+
* @param prefix - Optional address prefix (defaults to config.address_prefix)
|
|
79
|
+
* @returns PublicKey instance derived from this private key
|
|
80
|
+
*/
|
|
81
|
+
createPublic(prefix?: string): PublicKey;
|
|
82
|
+
/**
|
|
83
|
+
* Returns the private key as a Wallet Import Format (WIF) encoded string.
|
|
84
|
+
* This includes network ID and checksum for safe storage/transmission.
|
|
85
|
+
*
|
|
86
|
+
* @returns WIF encoded private key string
|
|
87
|
+
*/
|
|
88
|
+
toString(): string;
|
|
89
|
+
/**
|
|
90
|
+
* Returns a masked representation of the private key for debugging/logging.
|
|
91
|
+
* Shows only the first and last 6 characters to avoid accidental exposure.
|
|
92
|
+
* Use toString() to get the full key for export/serialization.
|
|
93
|
+
*
|
|
94
|
+
* @returns Masked key representation for safe logging
|
|
95
|
+
*/
|
|
96
|
+
inspect(): string;
|
|
97
|
+
/**
|
|
98
|
+
* Computes a shared secret using ECDH key exchange for memo encryption.
|
|
99
|
+
* The shared secret is used as a key for AES encryption/decryption.
|
|
100
|
+
*
|
|
101
|
+
* @param publicKey - Other party's public key
|
|
102
|
+
* @returns 64-byte shared secret as Uint8Array
|
|
103
|
+
*/
|
|
104
|
+
getSharedSecret(publicKey: PublicKey): Uint8Array;
|
|
105
|
+
/**
|
|
106
|
+
* Generates a new cryptographically secure random private key.
|
|
107
|
+
* Uses the secp256k1 key generation algorithm for security.
|
|
108
|
+
* This method may take up to 250ms due to entropy collection.
|
|
109
|
+
*
|
|
110
|
+
* @returns New randomly generated PrivateKey instance
|
|
111
|
+
*/
|
|
112
|
+
static randomKey(): PrivateKey;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=PrivateKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrivateKey.d.ts","sourceRoot":"","sources":["../../../src/helpers/PrivateKey.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAI7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,UAAU;IACrB,GAAG,EAAE,UAAU,CAAA;gBAEH,GAAG,EAAE,UAAU;IAS3B;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU;IAQnD;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAI1C;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU;IAatD;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,OAAkB,GAAG,UAAU;IAK1F;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS;IAUpC;;;;;OAKG;IACH,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS;IAIxC;;;;;OAKG;IACH,QAAQ,IAAI,MAAM;IAIlB;;;;;;OAMG;IACH,OAAO,IAAI,MAAM;IAKjB;;;;;;OAMG;IACH,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU;IAMjD;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,IAAI,UAAU;CAG/B"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import bs58 from 'bs58';
|
|
2
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
3
|
+
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
4
|
+
import { PublicKey } from './PublicKey';
|
|
5
|
+
import { Signature } from './Signature';
|
|
6
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
|
|
7
|
+
const NETWORK_ID = new Uint8Array([0x80]);
|
|
8
|
+
/**
|
|
9
|
+
* ECDSA (secp256k1) private key for signing and encryption operations.
|
|
10
|
+
* Handles key generation, derivation from seeds/passwords, and cryptographic operations.
|
|
11
|
+
*
|
|
12
|
+
* All private keys are stored internally as Uint8Array and can be converted to/from
|
|
13
|
+
* Wallet Import Format (WIF) strings for storage and transmission.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // From WIF string
|
|
18
|
+
* const key = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')
|
|
19
|
+
*
|
|
20
|
+
* // Generate random key
|
|
21
|
+
* const randomKey = PrivateKey.randomKey()
|
|
22
|
+
*
|
|
23
|
+
* // From username and password
|
|
24
|
+
* const loginKey = PrivateKey.fromLogin('username', 'password')
|
|
25
|
+
*
|
|
26
|
+
* // Sign a message
|
|
27
|
+
* const signature = key.sign(someHash)
|
|
28
|
+
*
|
|
29
|
+
* // Get public key
|
|
30
|
+
* const pubKey = key.createPublic()
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class PrivateKey {
|
|
34
|
+
constructor(key) {
|
|
35
|
+
this.key = key;
|
|
36
|
+
try {
|
|
37
|
+
secp256k1.getPublicKey(key);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new Error('invalid private key');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates a PrivateKey instance from a WIF string or raw Uint8Array.
|
|
45
|
+
* Automatically detects the input type and uses the appropriate method.
|
|
46
|
+
*
|
|
47
|
+
* @param value - WIF formatted string or raw 32-byte key as Uint8Array
|
|
48
|
+
* @returns New PrivateKey instance
|
|
49
|
+
* @throws Error if the key format is invalid
|
|
50
|
+
*/
|
|
51
|
+
static from(value) {
|
|
52
|
+
if (typeof value === 'string') {
|
|
53
|
+
return PrivateKey.fromString(value);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return new PrivateKey(value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates a PrivateKey from a Wallet Import Format (WIF) encoded string.
|
|
61
|
+
*
|
|
62
|
+
* @param wif - WIF encoded private key string
|
|
63
|
+
* @returns New PrivateKey instance
|
|
64
|
+
* @throws Error if WIF format is invalid or checksum fails
|
|
65
|
+
*/
|
|
66
|
+
static fromString(wif) {
|
|
67
|
+
return new PrivateKey(decodePrivate(wif).subarray(1));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates a PrivateKey from a seed string or Uint8Array.
|
|
71
|
+
* The seed is hashed with SHA256 to produce the private key.
|
|
72
|
+
*
|
|
73
|
+
* @param seed - Seed string (converted to bytes) or raw byte array
|
|
74
|
+
* @returns New PrivateKey instance derived from seed
|
|
75
|
+
*/
|
|
76
|
+
static fromSeed(seed) {
|
|
77
|
+
if (typeof seed === 'string') {
|
|
78
|
+
const isHex = /^[0-9a-fA-F]+$/.test(seed);
|
|
79
|
+
if (isHex) {
|
|
80
|
+
seed = hexToBytes(seed);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Convert non-hex string to Uint8Array using UTF-8 encoding
|
|
84
|
+
seed = new TextEncoder().encode(seed);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return new PrivateKey(sha256(seed));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Derives a PrivateKey from username, password, and role using Hive's key derivation scheme.
|
|
91
|
+
* This generates the same keys that the Hive wallet uses for login-based keys.
|
|
92
|
+
*
|
|
93
|
+
* @param username - Hive username
|
|
94
|
+
* @param password - Master password (or seed phrase)
|
|
95
|
+
* @param role - Key role ('owner', 'active', 'posting', 'memo')
|
|
96
|
+
* @returns New PrivateKey instance for the specified role
|
|
97
|
+
*/
|
|
98
|
+
static fromLogin(username, password, role = 'active') {
|
|
99
|
+
const seed = username + role + password;
|
|
100
|
+
return PrivateKey.fromSeed(seed);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Signs a 32-byte message hash using ECDSA and returns a recoverable signature.
|
|
104
|
+
* The signature includes recovery information to allow public key recovery.
|
|
105
|
+
*
|
|
106
|
+
* @param message - 32-byte message hash to sign (Uint8Array)
|
|
107
|
+
* @returns Signature object containing the signature data
|
|
108
|
+
*/
|
|
109
|
+
sign(message) {
|
|
110
|
+
const rv = secp256k1.sign(message, this.key, {
|
|
111
|
+
extraEntropy: true,
|
|
112
|
+
format: 'recovered',
|
|
113
|
+
prehash: false // prehash does sha256 on the message
|
|
114
|
+
});
|
|
115
|
+
const recovery = parseInt(bytesToHex(rv.subarray(0, 1)), 16);
|
|
116
|
+
return Signature.from((recovery + 31).toString(16) + bytesToHex(rv.subarray(1)));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Derives the corresponding public key for this private key.
|
|
120
|
+
*
|
|
121
|
+
* @param prefix - Optional address prefix (defaults to config.address_prefix)
|
|
122
|
+
* @returns PublicKey instance derived from this private key
|
|
123
|
+
*/
|
|
124
|
+
createPublic(prefix) {
|
|
125
|
+
return new PublicKey(secp256k1.getPublicKey(this.key), prefix);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Returns the private key as a Wallet Import Format (WIF) encoded string.
|
|
129
|
+
* This includes network ID and checksum for safe storage/transmission.
|
|
130
|
+
*
|
|
131
|
+
* @returns WIF encoded private key string
|
|
132
|
+
*/
|
|
133
|
+
toString() {
|
|
134
|
+
return encodePrivate(new Uint8Array([...NETWORK_ID, ...this.key]));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns a masked representation of the private key for debugging/logging.
|
|
138
|
+
* Shows only the first and last 6 characters to avoid accidental exposure.
|
|
139
|
+
* Use toString() to get the full key for export/serialization.
|
|
140
|
+
*
|
|
141
|
+
* @returns Masked key representation for safe logging
|
|
142
|
+
*/
|
|
143
|
+
inspect() {
|
|
144
|
+
const key = this.toString();
|
|
145
|
+
return `PrivateKey: ${key.slice(0, 6)}...${key.slice(-6)}`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Computes a shared secret using ECDH key exchange for memo encryption.
|
|
149
|
+
* The shared secret is used as a key for AES encryption/decryption.
|
|
150
|
+
*
|
|
151
|
+
* @param publicKey - Other party's public key
|
|
152
|
+
* @returns 64-byte shared secret as Uint8Array
|
|
153
|
+
*/
|
|
154
|
+
getSharedSecret(publicKey) {
|
|
155
|
+
const s = secp256k1.getSharedSecret(this.key, publicKey.key);
|
|
156
|
+
// strip the parity byte
|
|
157
|
+
return sha512(s.subarray(1));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Generates a new cryptographically secure random private key.
|
|
161
|
+
* Uses the secp256k1 key generation algorithm for security.
|
|
162
|
+
* This method may take up to 250ms due to entropy collection.
|
|
163
|
+
*
|
|
164
|
+
* @returns New randomly generated PrivateKey instance
|
|
165
|
+
*/
|
|
166
|
+
static randomKey() {
|
|
167
|
+
return new PrivateKey(secp256k1.keygen().secretKey);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const doubleSha256 = (input) => {
|
|
171
|
+
const dbl = sha256(sha256(input));
|
|
172
|
+
return dbl;
|
|
173
|
+
};
|
|
174
|
+
/** Encode bs58+doubleSha256-checksum private key. */
|
|
175
|
+
const encodePrivate = (key) => {
|
|
176
|
+
// assert.equal(key.readUInt8(0), 0x80, 'private key network id mismatch')
|
|
177
|
+
const checksum = doubleSha256(key);
|
|
178
|
+
return bs58.encode(new Uint8Array([...key, ...checksum.slice(0, 4)]));
|
|
179
|
+
};
|
|
180
|
+
/** Decode bs58+doubleSha256-checksum encoded private key. */
|
|
181
|
+
const decodePrivate = (encodedKey) => {
|
|
182
|
+
const buffer = bs58.decode(encodedKey);
|
|
183
|
+
if (!isUint8ArrayEqual(buffer.slice(0, 1), NETWORK_ID)) {
|
|
184
|
+
throw new Error('Private key network id mismatch');
|
|
185
|
+
}
|
|
186
|
+
const checksum = buffer.slice(-4);
|
|
187
|
+
const key = buffer.slice(0, -4);
|
|
188
|
+
const checksumVerify = doubleSha256(key).slice(0, 4);
|
|
189
|
+
if (!isUint8ArrayEqual(checksum, checksumVerify)) {
|
|
190
|
+
throw new Error('Private key checksum mismatch');
|
|
191
|
+
}
|
|
192
|
+
return key;
|
|
193
|
+
};
|
|
194
|
+
const isUint8ArrayEqual = (a, b) => {
|
|
195
|
+
if (a === b)
|
|
196
|
+
return true;
|
|
197
|
+
if (a.byteLength !== b.byteLength)
|
|
198
|
+
return false;
|
|
199
|
+
const len = a.byteLength;
|
|
200
|
+
let i = 0;
|
|
201
|
+
while (i < len && a[i] === b[i])
|
|
202
|
+
i++;
|
|
203
|
+
return i === len;
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=PrivateKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrivateKey.js","sourceRoot":"","sources":["../../../src/helpers/PrivateKey.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAI/D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,UAAU;IAGrB,YAAY,GAAe;QACzB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC;YACH,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,KAA0B;QACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,GAAW;QAC3B,OAAO,IAAI,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACvD,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAyB;QACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzC,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;iBAAM,CAAC;gBACN,4DAA4D;gBAC5D,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACvC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IACrC,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,CAAC,QAAgB,EAAE,QAAgB,EAAE,OAAgB,QAAQ;QAC3E,MAAM,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,QAAQ,CAAA;QACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,OAAmB;QACtB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;YAC3C,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,WAAW;YACnB,OAAO,EAAE,KAAK,CAAC,qCAAqC;SACrD,CAAC,CAAA;QACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5D,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAClF,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,MAAe;QAC1B,OAAO,IAAI,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;IAChE,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACN,OAAO,aAAa,CAAC,IAAI,UAAU,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACpE,CAAC;IAED;;;;;;OAMG;IACH,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC3B,OAAO,eAAe,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5D,CAAC;IAED;;;;;;OAMG;IACH,eAAe,CAAC,SAAoB;QAClC,MAAM,CAAC,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;QAC5D,wBAAwB;QACxB,OAAO,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9B,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,SAAS;QACd,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,CAAC;CACF;AAED,MAAM,YAAY,GAAG,CAAC,KAAiB,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;IACjC,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,qDAAqD;AACrD,MAAM,aAAa,GAAG,CAAC,GAAe,EAAE,EAAE;IACxC,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAClC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACvE,CAAC,CAAA;AAED,6DAA6D;AAC7D,MAAM,aAAa,GAAG,CAAC,UAAkB,EAAE,EAAE;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACtC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/B,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACpD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAClD,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,CAAC,CAAa,EAAE,CAAa,EAAE,EAAE;IACzD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAC/C,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,CAAA;IACxB,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAE,CAAC,EAAE,CAAA;IACpC,OAAO,CAAC,KAAK,GAAG,CAAA;AAClB,CAAC,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Signature } from './Signature';
|
|
2
|
+
export declare class PublicKey {
|
|
3
|
+
key: Uint8Array;
|
|
4
|
+
prefix: string;
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new PublicKey instance from raw bytes.
|
|
7
|
+
* @param key Raw public key bytes (33 bytes, compressed format)
|
|
8
|
+
* @param prefix Optional address prefix (defaults to config.address_prefix)
|
|
9
|
+
*/
|
|
10
|
+
constructor(key: Uint8Array, prefix?: string);
|
|
11
|
+
/**
|
|
12
|
+
* Creates a PublicKey from a string representation.
|
|
13
|
+
* @param wif Public key string (e.g., "STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA")
|
|
14
|
+
* @returns New PublicKey instance
|
|
15
|
+
* @throws Error if the key format is invalid
|
|
16
|
+
*/
|
|
17
|
+
static fromString(wif: string): PublicKey;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a PublicKey from a string or returns the instance if already a PublicKey.
|
|
20
|
+
* @param value Public key string or PublicKey instance
|
|
21
|
+
* @returns New or existing PublicKey instance
|
|
22
|
+
*/
|
|
23
|
+
static from(value: string | PublicKey): PublicKey;
|
|
24
|
+
/**
|
|
25
|
+
* Verifies a signature against a message hash.
|
|
26
|
+
* @param message 32-byte message hash to verify
|
|
27
|
+
* @param signature Signature to verify
|
|
28
|
+
* @returns True if signature is valid, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
verify(message: Uint8Array, signature: Signature | string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the public key as a string for storage or transmission.
|
|
33
|
+
* @returns Public key string with prefix (e.g., "STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA")
|
|
34
|
+
*/
|
|
35
|
+
toString(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Returns JSON representation (same as toString()).
|
|
38
|
+
* @returns Public key string
|
|
39
|
+
*/
|
|
40
|
+
toJSON(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a string representation for debugging.
|
|
43
|
+
* @returns Formatted public key string
|
|
44
|
+
*/
|
|
45
|
+
inspect(): string;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=PublicKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicKey.d.ts","sourceRoot":"","sources":["../../../src/helpers/PublicKey.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvC,qBAAa,SAAS;IACpB,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IAEd;;;;OAIG;gBACS,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM;IAM5C;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAKzC;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAQjD;;;;;OAKG;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO;IAUnE;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAIlB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAIhB;;;OAGG;IACH,OAAO,IAAI,MAAM;CAGlB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ripemd160 } from '@noble/hashes/legacy.js';
|
|
2
|
+
import bs58 from 'bs58';
|
|
3
|
+
import { config } from '../config';
|
|
4
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
5
|
+
import { Signature } from './Signature';
|
|
6
|
+
const DEFAULT_ADDRESS_PREFIX = config.address_prefix;
|
|
7
|
+
export class PublicKey {
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new PublicKey instance from raw bytes.
|
|
10
|
+
* @param key Raw public key bytes (33 bytes, compressed format)
|
|
11
|
+
* @param prefix Optional address prefix (defaults to config.address_prefix)
|
|
12
|
+
*/
|
|
13
|
+
constructor(key, prefix) {
|
|
14
|
+
this.key = key;
|
|
15
|
+
this.prefix = prefix ?? DEFAULT_ADDRESS_PREFIX;
|
|
16
|
+
// assert(secp256k1.publicKeyVerify(key), 'invalid public key')
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a PublicKey from a string representation.
|
|
20
|
+
* @param wif Public key string (e.g., "STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA")
|
|
21
|
+
* @returns New PublicKey instance
|
|
22
|
+
* @throws Error if the key format is invalid
|
|
23
|
+
*/
|
|
24
|
+
static fromString(wif) {
|
|
25
|
+
const { key, prefix } = decodePublic(wif);
|
|
26
|
+
return new PublicKey(key, prefix);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a PublicKey from a string or returns the instance if already a PublicKey.
|
|
30
|
+
* @param value Public key string or PublicKey instance
|
|
31
|
+
* @returns New or existing PublicKey instance
|
|
32
|
+
*/
|
|
33
|
+
static from(value) {
|
|
34
|
+
if (value instanceof PublicKey) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return PublicKey.fromString(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Verifies a signature against a message hash.
|
|
43
|
+
* @param message 32-byte message hash to verify
|
|
44
|
+
* @param signature Signature to verify
|
|
45
|
+
* @returns True if signature is valid, false otherwise
|
|
46
|
+
*/
|
|
47
|
+
verify(message, signature) {
|
|
48
|
+
if (typeof signature === 'string') {
|
|
49
|
+
signature = Signature.from(signature);
|
|
50
|
+
}
|
|
51
|
+
return secp256k1.verify(signature.data, message, this.key, {
|
|
52
|
+
prehash: false,
|
|
53
|
+
format: 'compact'
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the public key as a string for storage or transmission.
|
|
58
|
+
* @returns Public key string with prefix (e.g., "STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA")
|
|
59
|
+
*/
|
|
60
|
+
toString() {
|
|
61
|
+
return encodePublic(this.key, this.prefix);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns JSON representation (same as toString()).
|
|
65
|
+
* @returns Public key string
|
|
66
|
+
*/
|
|
67
|
+
toJSON() {
|
|
68
|
+
return this.toString();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Returns a string representation for debugging.
|
|
72
|
+
* @returns Formatted public key string
|
|
73
|
+
*/
|
|
74
|
+
inspect() {
|
|
75
|
+
return `PublicKey: ${this.toString()}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const encodePublic = (key, prefix) => {
|
|
79
|
+
const checksum = ripemd160(key);
|
|
80
|
+
return prefix + bs58.encode(new Uint8Array([...key, ...checksum.subarray(0, 4)]));
|
|
81
|
+
};
|
|
82
|
+
/** Decode bs58+ripemd160-checksum encoded public key. */
|
|
83
|
+
const decodePublic = (encodedKey) => {
|
|
84
|
+
const prefix = encodedKey.slice(0, 3);
|
|
85
|
+
encodedKey = encodedKey.slice(3);
|
|
86
|
+
const buffer = bs58.decode(encodedKey);
|
|
87
|
+
const key = buffer.subarray(0, buffer.length - 4);
|
|
88
|
+
return { key: key, prefix };
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=PublicKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicKey.js","sourceRoot":"","sources":["../../../src/helpers/PublicKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,MAAM,sBAAsB,GAAG,MAAM,CAAC,cAAc,CAAA;AAEpD,MAAM,OAAO,SAAS;IAIpB;;;;OAIG;IACH,YAAY,GAAe,EAAE,MAAe;QAC1C,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,sBAAsB,CAAA;QAC9C,+DAA+D;IACjE,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,GAAW;QAC3B,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QACzC,OAAO,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACnC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,KAAyB;QACnC,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAA;QACd,CAAC;aAAM,CAAC;YACN,OAAO,SAAS,CAAC,UAAU,CAAC,KAAe,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAmB,EAAE,SAA6B;QACvD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;YACzD,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,SAAS;SAClB,CAAC,CAAA;IACJ,CAAC;IAED;;;OAGG;IACH,QAAQ;QACN,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAA;IACxB,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,OAAO,cAAc,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAA;IACxC,CAAC;CACF;AAED,MAAM,YAAY,GAAG,CAAC,GAAe,EAAE,MAAc,EAAU,EAAE;IAC/D,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC/B,OAAO,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACnF,CAAC,CAAA;AAED,yDAAyD;AACzD,MAAM,YAAY,GAAG,CAAC,UAAkB,EAAE,EAAE;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACrC,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACjD,OAAO,EAAE,GAAG,EAAE,GAAiB,EAAE,MAAM,EAAE,CAAA;AAC3C,CAAC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { PublicKey } from './PublicKey';
|
|
2
|
+
export declare class Signature {
|
|
3
|
+
data: Uint8Array;
|
|
4
|
+
recovery: number;
|
|
5
|
+
private compressed;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new Signature instance.
|
|
8
|
+
* @param data Raw signature data (64 bytes)
|
|
9
|
+
* @param recovery Recovery byte (0-3)
|
|
10
|
+
* @param compressed Whether signature is compressed (default: true)
|
|
11
|
+
*/
|
|
12
|
+
constructor(data: Uint8Array, recovery: number, compressed?: boolean);
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Signature from a hex string.
|
|
15
|
+
* @param string 130-character hex string containing signature and recovery data
|
|
16
|
+
* @returns New Signature instance
|
|
17
|
+
* @throws Error if input is not a string
|
|
18
|
+
*/
|
|
19
|
+
static from(string: string): Signature;
|
|
20
|
+
/**
|
|
21
|
+
* Converts signature to 65-byte buffer format.
|
|
22
|
+
* @returns 65-byte buffer containing recovery byte + signature data
|
|
23
|
+
*/
|
|
24
|
+
toBuffer(): Uint8Array<ArrayBuffer>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns signature as 130-character hex string.
|
|
27
|
+
* @returns Hex string representation of signature
|
|
28
|
+
*/
|
|
29
|
+
customToString(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Recovers the public key from this signature and message.
|
|
32
|
+
* @param message 32-byte message hash (Uint8Array) or 64-character hex string
|
|
33
|
+
* @returns PublicKey that created this signature
|
|
34
|
+
* @throws Error if message is not a valid 32-byte SHA256 hash
|
|
35
|
+
*/
|
|
36
|
+
getPublicKey(message: Uint8Array | string): PublicKey;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=Signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Signature.d.ts","sourceRoot":"","sources":["../../../src/helpers/Signature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvC,qBAAa,SAAS;IACpB,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;OAKG;gBACS,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO;IAMpE;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAkB1B;;;OAGG;IACH,QAAQ;IAWR;;;OAGG;IACH,cAAc;IAId;;;;;OAKG;IACH,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS;CActD"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PublicKey } from './PublicKey';
|
|
2
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
3
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
|
|
4
|
+
export class Signature {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new Signature instance.
|
|
7
|
+
* @param data Raw signature data (64 bytes)
|
|
8
|
+
* @param recovery Recovery byte (0-3)
|
|
9
|
+
* @param compressed Whether signature is compressed (default: true)
|
|
10
|
+
*/
|
|
11
|
+
constructor(data, recovery, compressed) {
|
|
12
|
+
this.data = data;
|
|
13
|
+
this.recovery = recovery;
|
|
14
|
+
this.compressed = compressed ?? true;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Signature from a hex string.
|
|
18
|
+
* @param string 130-character hex string containing signature and recovery data
|
|
19
|
+
* @returns New Signature instance
|
|
20
|
+
* @throws Error if input is not a string
|
|
21
|
+
*/
|
|
22
|
+
static from(string) {
|
|
23
|
+
if (typeof string === 'string') {
|
|
24
|
+
const temp = hexToBytes(string);
|
|
25
|
+
let recovery = parseInt(bytesToHex(temp.subarray(0, 1)), 16) - 31;
|
|
26
|
+
let compressed = true;
|
|
27
|
+
// non-compressed signatures have -4
|
|
28
|
+
// https://github.com/bitcoin/bitcoin/blob/95ea54ba089610019a74c1176a2c7c0dba144b1c/src/key.cpp#L257
|
|
29
|
+
if (recovery < 0) {
|
|
30
|
+
compressed = false;
|
|
31
|
+
recovery = recovery + 4;
|
|
32
|
+
}
|
|
33
|
+
const data = temp.subarray(1);
|
|
34
|
+
return new Signature(data, recovery, compressed);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
throw new Error('Expected string for data');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Converts signature to 65-byte buffer format.
|
|
42
|
+
* @returns 65-byte buffer containing recovery byte + signature data
|
|
43
|
+
*/
|
|
44
|
+
toBuffer() {
|
|
45
|
+
const buffer = new Uint8Array(65).fill(0);
|
|
46
|
+
if (this.compressed) {
|
|
47
|
+
buffer[0] = (this.recovery + 31) & 0xff;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
buffer[0] = (this.recovery + 27) & 0xff;
|
|
51
|
+
}
|
|
52
|
+
buffer.set(this.data, 1);
|
|
53
|
+
return buffer;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns signature as 130-character hex string.
|
|
57
|
+
* @returns Hex string representation of signature
|
|
58
|
+
*/
|
|
59
|
+
customToString() {
|
|
60
|
+
return bytesToHex(this.toBuffer());
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Recovers the public key from this signature and message.
|
|
64
|
+
* @param message 32-byte message hash (Uint8Array) or 64-character hex string
|
|
65
|
+
* @returns PublicKey that created this signature
|
|
66
|
+
* @throws Error if message is not a valid 32-byte SHA256 hash
|
|
67
|
+
*/
|
|
68
|
+
getPublicKey(message) {
|
|
69
|
+
if ((message instanceof Uint8Array && message.length !== 32) ||
|
|
70
|
+
(typeof message === 'string' && message.length !== 64)) {
|
|
71
|
+
throw new Error('Expected a valid sha256 hash as message');
|
|
72
|
+
}
|
|
73
|
+
if (typeof message === 'string') {
|
|
74
|
+
message = hexToBytes(message);
|
|
75
|
+
}
|
|
76
|
+
const sig = secp256k1.Signature.fromBytes(this.data, 'compact');
|
|
77
|
+
const temp = new secp256k1.Signature(sig.r, sig.s, this.recovery);
|
|
78
|
+
return new PublicKey(temp.recoverPublicKey(message).toBytes());
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=Signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Signature.js","sourceRoot":"","sources":["../../../src/helpers/Signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PrivateKey } from './PrivateKey';
|
|
2
|
+
import { PublicKey } from './PublicKey';
|
|
3
|
+
export declare const encrypt: (privateKey: PrivateKey, publicKey: PublicKey, message: Uint8Array, nonce?: bigint) => {
|
|
4
|
+
nonce: bigint;
|
|
5
|
+
message: Uint8Array;
|
|
6
|
+
checksum: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const decrypt: (privateKey: PrivateKey, publicKey: PublicKey, nonce: bigint, message: Uint8Array, checksum: number) => Uint8Array;
|
|
9
|
+
/**
|
|
10
|
+
* This method does not use a checksum, the returned data must be validated some other way.
|
|
11
|
+
* @arg {string|Uint8Array} plaintext - binary format
|
|
12
|
+
* @return {Uint8Array} binary
|
|
13
|
+
*/
|
|
14
|
+
export declare const cryptoJsEncrypt: (message: Uint8Array, tag: Uint8Array, iv: Uint8Array) => Uint8Array;
|
|
15
|
+
//# sourceMappingURL=aes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../../../src/helpers/aes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,eAAO,MAAM,OAAO,GAClB,YAAY,UAAU,EACtB,WAAW,SAAS,EACpB,SAAS,UAAU,EACnB,QAAO,MAAsB;WAwBnB,MAAM;aAAW,UAAU;cAAY,MAAM;CAvBR,CAAA;AAEjD,eAAO,MAAM,OAAO,GAClB,YAAY,UAAU,EACtB,WAAW,SAAS,EACpB,OAAO,MAAM,EACb,SAAS,UAAU,EACnB,UAAU,MAAM,KACf,UAGF,CAAA;AAsDD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,UAAU,EACnB,KAAK,UAAU,EACf,IAAI,UAAU,KACb,UAMF,CAAA"}
|