chainproof 0.1.0 → 0.2.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/README.md +233 -0
- package/dist/crypto.d.ts +2 -2
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +56 -56
- package/dist/crypto.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# chainproof
|
|
2
|
+
|
|
3
|
+
Hash-chained, Ed25519-signed append-only logs for TypeScript. Tamper-evident audit trails as a reusable primitive.
|
|
4
|
+
|
|
5
|
+
## Why chainproof?
|
|
6
|
+
|
|
7
|
+
Any system that needs a provable, tamper-evident history of events — audit logs, receipt chains, compliance trails, change tracking — needs three things:
|
|
8
|
+
|
|
9
|
+
1. **Hash linking** — each entry commits to the previous one, so deletions and reordering are detectable
|
|
10
|
+
2. **Signatures** — each entry is cryptographically signed, so forgery requires the private key
|
|
11
|
+
3. **Verification** — anyone with the public key can verify the entire chain without trusting the writer
|
|
12
|
+
|
|
13
|
+
chainproof gives you all three in a single library. No database required — just append entries and verify.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install chainproof
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { ChainLog, generateKeyPair } from 'chainproof'
|
|
25
|
+
|
|
26
|
+
// Generate Ed25519 key pair
|
|
27
|
+
const keyPair = generateKeyPair().unwrap()
|
|
28
|
+
|
|
29
|
+
// Create a chain and append entries
|
|
30
|
+
const chain = new ChainLog(keyPair)
|
|
31
|
+
|
|
32
|
+
chain.append({ tool: 'Edit', file: 'server.ts', user: 'alice' })
|
|
33
|
+
chain.append({ tool: 'Bash', command: 'pnpm test', user: 'alice' })
|
|
34
|
+
chain.append({ tool: 'Deploy', target: 'production', user: 'bob' })
|
|
35
|
+
|
|
36
|
+
// Verify the entire chain
|
|
37
|
+
const result = chain.verifyIntegrity()
|
|
38
|
+
console.log(result)
|
|
39
|
+
// { valid: true, chainLength: 3, lastValidSeq: 2, message: 'Chain verified: 3 entries' }
|
|
40
|
+
|
|
41
|
+
// Tamper with an entry — verification catches it
|
|
42
|
+
const tampered = chain.entries.map((e, i) =>
|
|
43
|
+
i === 0 ? { ...e, data: { tool: 'FORGED', file: 'evil.ts', user: 'alice' } } : e
|
|
44
|
+
)
|
|
45
|
+
const check = ChainLog.verify(tampered, keyPair.publicKey)
|
|
46
|
+
console.log(check.valid) // false
|
|
47
|
+
console.log(check.message) // 'Seq 0: invalid signature'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## How It Works
|
|
51
|
+
|
|
52
|
+
Each entry in the chain contains:
|
|
53
|
+
|
|
54
|
+
| Field | Description |
|
|
55
|
+
|-------|-------------|
|
|
56
|
+
| `id` | UUIDv7 (time-ordered, RFC 9562) |
|
|
57
|
+
| `seq` | Monotonic sequence number |
|
|
58
|
+
| `timestamp` | Unix timestamp |
|
|
59
|
+
| `data` | Your payload (generic `T`) |
|
|
60
|
+
| `dataHash` | SHA-256 of canonical JSON of `data` |
|
|
61
|
+
| `prevHash` | SHA-256 of previous entry's canonical bytes |
|
|
62
|
+
| `signature` | Ed25519 signature (base64) |
|
|
63
|
+
|
|
64
|
+
**Genesis**: The first entry links to `SHA-256("chainproof:genesis")`.
|
|
65
|
+
|
|
66
|
+
**Canonical form**: Entries are serialized with sorted keys and the `signature` field excluded before hashing and signing. This ensures deterministic verification regardless of JSON key ordering.
|
|
67
|
+
|
|
68
|
+
**Tamper detection**:
|
|
69
|
+
- Modify any field → signature verification fails
|
|
70
|
+
- Delete an entry → next entry's `prevHash` no longer matches
|
|
71
|
+
- Reorder entries → hash chain breaks
|
|
72
|
+
- Forge an entry → requires the private key
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Chain Operations
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { ChainLog, generateKeyPair } from 'chainproof'
|
|
80
|
+
|
|
81
|
+
const keyPair = generateKeyPair().unwrap()
|
|
82
|
+
const chain = new ChainLog<{ action: string; user: string }>(keyPair)
|
|
83
|
+
|
|
84
|
+
// Append returns Result<ChainEntry<T>, ChainError>
|
|
85
|
+
const entry = chain.append({ action: 'create', user: 'alice' })
|
|
86
|
+
if (entry.isOk()) {
|
|
87
|
+
console.log(entry.value.id) // '019d1263-...'
|
|
88
|
+
console.log(entry.value.seq) // 0
|
|
89
|
+
console.log(entry.value.signature) // 'base64...'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Access entries
|
|
93
|
+
console.log(chain.length) // 1
|
|
94
|
+
console.log(chain.entries) // readonly ChainEntry<T>[]
|
|
95
|
+
console.log(chain.lastHash) // SHA-256 of last entry
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Verification
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// Verify using the chain's own key pair
|
|
102
|
+
const result = chain.verifyIntegrity()
|
|
103
|
+
|
|
104
|
+
// Or verify externally with just the public key
|
|
105
|
+
const result = ChainLog.verify(entries, publicKey)
|
|
106
|
+
|
|
107
|
+
// Result shape
|
|
108
|
+
// { valid: boolean, chainLength: number, lastValidSeq: number, message: string }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### JSONL Serialization
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Serialize to JSONL (one JSON entry per line)
|
|
115
|
+
const jsonl = chain.toJsonl()
|
|
116
|
+
|
|
117
|
+
// Restore from JSONL
|
|
118
|
+
const restored = ChainLog.fromJsonl(jsonl, keyPair)
|
|
119
|
+
if (restored.isOk()) {
|
|
120
|
+
console.log(restored.value.length) // same as original
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### File Storage
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { appendToFile, readFromFile, saveChainToFile, loadChainFromFile } from 'chainproof'
|
|
128
|
+
|
|
129
|
+
// Append entries one at a time (ideal for live logging)
|
|
130
|
+
const entry = chain.append({ action: 'deploy' }).unwrap()
|
|
131
|
+
await appendToFile('/var/log/audit.jsonl', entry)
|
|
132
|
+
|
|
133
|
+
// Read entries from file
|
|
134
|
+
const entries = await readFromFile('/var/log/audit.jsonl')
|
|
135
|
+
|
|
136
|
+
// Save/load entire chain
|
|
137
|
+
await saveChainToFile('/var/log/audit.jsonl', chain)
|
|
138
|
+
const loaded = await loadChainFromFile('/var/log/audit.jsonl', keyPair)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Key Management
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import {
|
|
145
|
+
generateKeyPair,
|
|
146
|
+
saveKeyPair,
|
|
147
|
+
loadKeyPair,
|
|
148
|
+
exportPublicKey,
|
|
149
|
+
importPublicKey
|
|
150
|
+
} from 'chainproof'
|
|
151
|
+
|
|
152
|
+
// Generate and save keys (private key gets 0o600 permissions)
|
|
153
|
+
const keyPair = generateKeyPair().unwrap()
|
|
154
|
+
await saveKeyPair(keyPair, '/etc/myapp/keys')
|
|
155
|
+
// Creates: /etc/myapp/keys/chain.key (private, 0o600)
|
|
156
|
+
// /etc/myapp/keys/chain.pub (public, 0o644)
|
|
157
|
+
|
|
158
|
+
// Load keys from disk
|
|
159
|
+
const loaded = await loadKeyPair('/etc/myapp/keys')
|
|
160
|
+
|
|
161
|
+
// Export public key for external verifiers
|
|
162
|
+
const pem = exportPublicKey(keyPair.publicKey)
|
|
163
|
+
// Share this PEM — anyone can verify the chain without the private key
|
|
164
|
+
|
|
165
|
+
// Import a public key for verification
|
|
166
|
+
const pubKey = importPublicKey(pem).unwrap()
|
|
167
|
+
const result = ChainLog.verify(entries, pubKey)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Low-Level API
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { sha256, sign, verify, canonicalJson, createEntry, entryHash, genesisHash, uuid7 } from 'chainproof'
|
|
174
|
+
|
|
175
|
+
// SHA-256 hashing
|
|
176
|
+
sha256('hello') // '2cf24dba...'
|
|
177
|
+
|
|
178
|
+
// Canonical JSON (sorted keys, deterministic)
|
|
179
|
+
canonicalJson({ z: 1, a: 2 }) // '{"a":2,"z":1}'
|
|
180
|
+
|
|
181
|
+
// Ed25519 sign/verify
|
|
182
|
+
const sig = sign(keyPair.privateKey, 'data').unwrap()
|
|
183
|
+
const valid = verify(keyPair.publicKey, 'data', sig).unwrap() // true
|
|
184
|
+
|
|
185
|
+
// UUIDv7 (time-ordered)
|
|
186
|
+
uuid7() // '019d1263-7a2b-7c58-...'
|
|
187
|
+
|
|
188
|
+
// Manual entry creation
|
|
189
|
+
const entry = createEntry({ action: 'test' }, 0, genesisHash(), keyPair)
|
|
190
|
+
const hash = entryHash(entry.unwrap())
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Error Handling
|
|
194
|
+
|
|
195
|
+
All fallible operations return `Result<T, ChainError>` or `ResultAsync<T, ChainError>` from [@valencets/resultkit](https://github.com/valencets/resultkit).
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface ChainError {
|
|
199
|
+
readonly code: ChainErrorCode
|
|
200
|
+
readonly message: string
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Error codes: INVALID_KEY, SIGN_FAILED, VERIFY_FAILED, CHAIN_BROKEN, IO_FAILED, PARSE_FAILED
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Cryptographic Primitives
|
|
207
|
+
|
|
208
|
+
| Primitive | Purpose | Implementation |
|
|
209
|
+
|-----------|---------|----------------|
|
|
210
|
+
| **SHA-256** | Hash chain links, data hashing | `node:crypto` (built-in) |
|
|
211
|
+
| **Ed25519** | Entry signing and verification | `node:crypto` (built-in) |
|
|
212
|
+
| **UUIDv7** | Time-ordered entry IDs | Custom (RFC 9562) |
|
|
213
|
+
| **Base64** | Signature encoding | Built-in |
|
|
214
|
+
|
|
215
|
+
No native addons. No npm crypto dependencies. Just `node:crypto`.
|
|
216
|
+
|
|
217
|
+
## Design Principles
|
|
218
|
+
|
|
219
|
+
1. **Append-only** — entries are never modified or deleted
|
|
220
|
+
2. **Externally verifiable** — anyone with the public key can verify (no shared secret)
|
|
221
|
+
3. **Deterministic** — canonical JSON serialization ensures consistent hashing
|
|
222
|
+
4. **Minimal** — one runtime dependency (`@valencets/resultkit`)
|
|
223
|
+
5. **Generic** — `ChainLog<T>` works with any serializable payload type
|
|
224
|
+
|
|
225
|
+
## Requirements
|
|
226
|
+
|
|
227
|
+
- Node.js >= 22
|
|
228
|
+
- TypeScript >= 5.9
|
|
229
|
+
- ESM only (`"type": "module"`)
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT
|
package/dist/crypto.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export declare function generateKeyPair(): Result<KeyPair, ChainError>;
|
|
|
10
10
|
export declare function sha256(data: string): string;
|
|
11
11
|
export declare function sign(privateKey: crypto.KeyObject, data: string): Result<string, ChainError>;
|
|
12
12
|
export declare function verify(publicKey: crypto.KeyObject, data: string, signature: string): Result<boolean, ChainError>;
|
|
13
|
-
export declare function exportPrivateKey(key: crypto.KeyObject): string
|
|
14
|
-
export declare function exportPublicKey(key: crypto.KeyObject): string
|
|
13
|
+
export declare function exportPrivateKey(key: crypto.KeyObject): Result<string, ChainError>;
|
|
14
|
+
export declare function exportPublicKey(key: crypto.KeyObject): Result<string, ChainError>;
|
|
15
15
|
export declare function importPrivateKey(pem: string): Result<crypto.KeyObject, ChainError>;
|
|
16
16
|
export declare function importPublicKey(pem: string): Result<crypto.KeyObject, ChainError>;
|
|
17
17
|
export declare function saveKeyPair(keyPair: KeyPair, dir: string): ResultAsync<void, ChainError>;
|
package/dist/crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,OAAO,
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,OAAO,EAA0B,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAA;CACrC;AAyDD,wBAAgB,eAAe,IAAK,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAE9D;AAED,wBAAgB,MAAM,CAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,IAAI,CAAE,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAE5F;AAED,wBAAgB,MAAM,CACpB,SAAS,EAAE,MAAM,CAAC,SAAS,EAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAE7B;AAED,wBAAgB,gBAAgB,CAAE,GAAG,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAEnF;AAED,wBAAgB,eAAe,CAAE,GAAG,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAElF;AAED,wBAAgB,gBAAgB,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAOnF;AAED,wBAAgB,eAAe,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAOlF;AAED,wBAAgB,WAAW,CAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAkBzF;AAED,wBAAgB,WAAW,CAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAiB1E"}
|
package/dist/crypto.js
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
|
-
import { ok, err, ResultAsync } from '@valencets/resultkit';
|
|
3
|
+
import { ok, err, fromThrowable, ResultAsync } from '@valencets/resultkit';
|
|
4
|
+
const safeGenerateKeyPair = fromThrowable(() => crypto.generateKeyPairSync('ed25519'), (e) => ({
|
|
5
|
+
code: 'INVALID_KEY',
|
|
6
|
+
message: e instanceof Error ? e.message : 'Key generation failed'
|
|
7
|
+
}));
|
|
8
|
+
const safeSign = fromThrowable((privateKey, data) => {
|
|
9
|
+
const signature = crypto.sign(null, Buffer.from(data, 'utf-8'), privateKey);
|
|
10
|
+
return signature.toString('base64');
|
|
11
|
+
}, (e) => ({
|
|
12
|
+
code: 'SIGN_FAILED',
|
|
13
|
+
message: e instanceof Error ? e.message : 'Signing failed'
|
|
14
|
+
}));
|
|
15
|
+
const safeVerify = fromThrowable((publicKey, data, signature) => {
|
|
16
|
+
const sigBuffer = Buffer.from(signature, 'base64');
|
|
17
|
+
return crypto.verify(null, Buffer.from(data, 'utf-8'), publicKey, sigBuffer);
|
|
18
|
+
}, (e) => ({
|
|
19
|
+
code: 'VERIFY_FAILED',
|
|
20
|
+
message: e instanceof Error ? e.message : 'Verification failed'
|
|
21
|
+
}));
|
|
22
|
+
const safeCreatePrivateKey = fromThrowable((pem) => crypto.createPrivateKey(pem), (e) => ({
|
|
23
|
+
code: 'INVALID_KEY',
|
|
24
|
+
message: e instanceof Error ? e.message : 'Invalid private key PEM'
|
|
25
|
+
}));
|
|
26
|
+
const safeCreatePublicKey = fromThrowable((pem) => crypto.createPublicKey(pem), (e) => ({
|
|
27
|
+
code: 'INVALID_KEY',
|
|
28
|
+
message: e instanceof Error ? e.message : 'Invalid public key PEM'
|
|
29
|
+
}));
|
|
30
|
+
const safeExportKey = fromThrowable((key, type, format) => String(key.export({ type, format })), (e) => ({
|
|
31
|
+
code: 'INVALID_KEY',
|
|
32
|
+
message: e instanceof Error ? e.message : 'Key export failed'
|
|
33
|
+
}));
|
|
4
34
|
export function generateKeyPair() {
|
|
5
|
-
|
|
6
|
-
const { privateKey, publicKey } = crypto.generateKeyPairSync('ed25519');
|
|
7
|
-
return ok({ privateKey, publicKey });
|
|
8
|
-
}
|
|
9
|
-
catch (e) {
|
|
10
|
-
return err({
|
|
11
|
-
code: 'INVALID_KEY',
|
|
12
|
-
message: e instanceof Error ? e.message : 'Key generation failed'
|
|
13
|
-
});
|
|
14
|
-
}
|
|
35
|
+
return safeGenerateKeyPair().map(({ privateKey, publicKey }) => ({ privateKey, publicKey }));
|
|
15
36
|
}
|
|
16
37
|
export function sha256(data) {
|
|
17
38
|
return crypto.createHash('sha256').update(data, 'utf-8').digest('hex');
|
|
18
39
|
}
|
|
19
40
|
export function sign(privateKey, data) {
|
|
20
|
-
|
|
21
|
-
const signature = crypto.sign(null, Buffer.from(data, 'utf-8'), privateKey);
|
|
22
|
-
return ok(signature.toString('base64'));
|
|
23
|
-
}
|
|
24
|
-
catch (e) {
|
|
25
|
-
return err({
|
|
26
|
-
code: 'SIGN_FAILED',
|
|
27
|
-
message: e instanceof Error ? e.message : 'Signing failed'
|
|
28
|
-
});
|
|
29
|
-
}
|
|
41
|
+
return safeSign(privateKey, data);
|
|
30
42
|
}
|
|
31
43
|
export function verify(publicKey, data, signature) {
|
|
32
|
-
|
|
33
|
-
const sigBuffer = Buffer.from(signature, 'base64');
|
|
34
|
-
const valid = crypto.verify(null, Buffer.from(data, 'utf-8'), publicKey, sigBuffer);
|
|
35
|
-
return ok(valid);
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
return err({
|
|
39
|
-
code: 'VERIFY_FAILED',
|
|
40
|
-
message: e instanceof Error ? e.message : 'Verification failed'
|
|
41
|
-
});
|
|
42
|
-
}
|
|
44
|
+
return safeVerify(publicKey, data, signature);
|
|
43
45
|
}
|
|
44
46
|
export function exportPrivateKey(key) {
|
|
45
|
-
return key
|
|
47
|
+
return safeExportKey(key, 'pkcs8', 'pem');
|
|
46
48
|
}
|
|
47
49
|
export function exportPublicKey(key) {
|
|
48
|
-
return key
|
|
50
|
+
return safeExportKey(key, 'spki', 'pem');
|
|
49
51
|
}
|
|
50
52
|
export function importPrivateKey(pem) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
message: e instanceof Error ? e.message : 'Invalid private key PEM'
|
|
58
|
-
});
|
|
59
|
-
}
|
|
53
|
+
return safeCreatePrivateKey(pem).andThen((key) => {
|
|
54
|
+
if (key.asymmetricKeyType !== 'ed25519') {
|
|
55
|
+
return err({ code: 'INVALID_KEY', message: `Expected Ed25519 key, got ${key.asymmetricKeyType}` });
|
|
56
|
+
}
|
|
57
|
+
return ok(key);
|
|
58
|
+
});
|
|
60
59
|
}
|
|
61
60
|
export function importPublicKey(pem) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
message: e instanceof Error ? e.message : 'Invalid public key PEM'
|
|
69
|
-
});
|
|
70
|
-
}
|
|
61
|
+
return safeCreatePublicKey(pem).andThen((key) => {
|
|
62
|
+
if (key.asymmetricKeyType !== 'ed25519') {
|
|
63
|
+
return err({ code: 'INVALID_KEY', message: `Expected Ed25519 key, got ${key.asymmetricKeyType}` });
|
|
64
|
+
}
|
|
65
|
+
return ok(key);
|
|
66
|
+
});
|
|
71
67
|
}
|
|
72
68
|
export function saveKeyPair(keyPair, dir) {
|
|
73
|
-
const
|
|
74
|
-
|
|
69
|
+
const privateResult = exportPrivateKey(keyPair.privateKey);
|
|
70
|
+
if (privateResult.isErr())
|
|
71
|
+
return privateResult.toAsync().map(() => undefined);
|
|
72
|
+
const publicResult = exportPublicKey(keyPair.publicKey);
|
|
73
|
+
if (publicResult.isErr())
|
|
74
|
+
return publicResult.toAsync().map(() => undefined);
|
|
75
75
|
return ResultAsync.fromPromise(fs.mkdir(dir, { recursive: true })
|
|
76
76
|
.then(() => Promise.all([
|
|
77
|
-
fs.writeFile(`${dir}/chain.key`,
|
|
78
|
-
fs.writeFile(`${dir}/chain.pub`,
|
|
77
|
+
fs.writeFile(`${dir}/chain.key`, privateResult.value, { mode: 0o600 }),
|
|
78
|
+
fs.writeFile(`${dir}/chain.pub`, publicResult.value, { mode: 0o644 })
|
|
79
79
|
]))
|
|
80
80
|
.then(() => undefined), (e) => ({
|
|
81
81
|
code: 'IO_FAILED',
|
package/dist/crypto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED