Skip to content

Commit 0f31dc3

Browse files
vveerrggclaude
andcommitted
feat: add NIP-49 ncryptsec support, upgrade to nostr-crypto-utils v0.5.1
Add toNcryptsec() and fromNcryptsec() for password-protected private key export/import using the NIP-49 ncryptsec bech32 format. Natural companion to BIP-39 seedphrase key derivation — users can now encrypt their derived keys for secure backup. Sensitive byte arrays are zeroed after use, consistent with existing codebase patterns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7b010d7 commit 0f31dc3

79 files changed

Lines changed: 996 additions & 483 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dist/__mocks__/@noble/secp256k1.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Mock implementation of @noble/secp256k1 for testing
2-
import { bytesToHex as originalBytesToHex, hexToBytes as originalHexToBytes } from "@noble/hashes/utils";
2+
import { bytesToHex as originalBytesToHex, hexToBytes as originalHexToBytes, } from "@noble/hashes/utils";
33
function ensureUint8Array(input) {
44
if (input instanceof Uint8Array)
55
return input;
6-
if (typeof input === 'string')
6+
if (typeof input === "string")
77
return originalHexToBytes(input);
8-
throw new Error('Input must be Uint8Array or hex string');
8+
throw new Error("Input must be Uint8Array or hex string");
99
}
1010
function createMockPublicKey(privateKey) {
1111
// Create a deterministic 33-byte compressed public key
@@ -21,7 +21,7 @@ function createMockPublicKey(privateKey) {
2121
export function getPublicKey(privateKey) {
2222
const privKeyBytes = ensureUint8Array(privateKey);
2323
if (privKeyBytes.length !== 32) {
24-
throw new Error('Private key must be 32 bytes');
24+
throw new Error("Private key must be 32 bytes");
2525
}
2626
return createMockPublicKey(privKeyBytes);
2727
}
@@ -40,7 +40,7 @@ export const schnorr = {
4040
},
4141
verify(signature, message, publicKey) {
4242
return Promise.resolve(true);
43-
}
43+
},
4444
};
4545
// Mock utility functions
4646
export const utils = {
@@ -61,10 +61,10 @@ export const utils = {
6161
privateKey[i] = Math.floor(Math.random() * 256);
6262
}
6363
return privateKey;
64-
}
64+
},
6565
};
6666
export default {
6767
getPublicKey,
6868
schnorr,
69-
utils
69+
utils,
7070
};

dist/__mocks__/bech32.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ function encode(prefix, words, limit) {
2424
}
2525
function decode(str, limit) {
2626
// Simple mock decoding: split on '1'
27-
const [prefix, data] = str.split('1');
27+
const [prefix, data] = str.split("1");
2828
if (!prefix || !data) {
29-
throw new Error('Invalid bech32 string');
29+
throw new Error("Invalid bech32 string");
3030
}
3131
const bytes = hexToBytes(data);
3232
return {
3333
prefix,
34-
words: Array.from(bytes).map(b => b & 0x1f) // Convert to 5-bit words
34+
words: Array.from(bytes).map((b) => b & 0x1f), // Convert to 5-bit words
3535
};
3636
}
3737
export const bech32 = {
3838
toWords,
3939
fromWords,
4040
encode,
41-
decode
41+
decode,
4242
};

dist/__mocks__/bip39.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function validateMnemonic(mnemonic) {
1313
return true;
1414
}
1515
const words = mnemonic.split(" ");
16-
const isValid = words.length === 12 && words.every(word => word.length > 0);
16+
const isValid = words.length === 12 && words.every((word) => word.length > 0);
1717
console.log(`Validation result for "${mnemonic}": ${isValid}`);
1818
return isValid;
1919
}

dist/bips/bip39.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { generateMnemonic, validateMnemonic, mnemonicToEntropy } from 'bip39';
2-
import { logger } from '../utils/logger';
1+
import { generateMnemonic, validateMnemonic, mnemonicToEntropy } from "bip39";
2+
import { logger } from "../utils/logger";
33
/**
44
* Generates a new BIP39 seed phrase
55
* @returns {string} The generated seed phrase
@@ -12,8 +12,8 @@ export function generateSeedPhrase() {
1212
return generateMnemonic();
1313
}
1414
catch (error) {
15-
logger.error('Failed to generate seed phrase:', error instanceof Error ? error.message : String(error));
16-
throw new Error('Failed to generate seed phrase');
15+
logger.error("Failed to generate seed phrase:", error instanceof Error ? error.message : String(error));
16+
throw new Error("Failed to generate seed phrase");
1717
}
1818
}
1919
/**
@@ -29,7 +29,7 @@ export function validateSeedPhrase(seedPhrase) {
2929
return validateMnemonic(seedPhrase);
3030
}
3131
catch (error) {
32-
logger.error('Failed to validate seed phrase:', error instanceof Error ? error.message : String(error));
32+
logger.error("Failed to validate seed phrase:", error instanceof Error ? error.message : String(error));
3333
return false;
3434
}
3535
}
@@ -45,7 +45,7 @@ export function validateSeedPhrase(seedPhrase) {
4545
export function getEntropyFromSeedPhrase(seedPhrase) {
4646
try {
4747
if (!validateSeedPhrase(seedPhrase)) {
48-
throw new Error('Invalid seed phrase');
48+
throw new Error("Invalid seed phrase");
4949
}
5050
// Convert the seed phrase to entropy bytes
5151
const entropyHex = mnemonicToEntropy(seedPhrase);
@@ -57,7 +57,7 @@ export function getEntropyFromSeedPhrase(seedPhrase) {
5757
return entropyBytes;
5858
}
5959
catch (error) {
60-
logger.error('Failed to get entropy from seed phrase:', error instanceof Error ? error.message : String(error));
61-
throw new Error('Failed to get entropy from seed phrase');
60+
logger.error("Failed to get entropy from seed phrase:", error instanceof Error ? error.message : String(error));
61+
throw new Error("Failed to get entropy from seed phrase");
6262
}
6363
}

dist/bips/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
* @module bips
33
* @description Bitcoin Improvement Proposals (BIPs) implementations
44
*/
5-
export * from './bip39.js';
5+
export * from "./bip39.js";

dist/bips/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
* @module bips
33
* @description Bitcoin Improvement Proposals (BIPs) implementations
44
*/
5-
export * from './bip39.js';
5+
export * from "./bip39.js";

dist/browser.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './index';
1+
export * from "./index";

dist/browser.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Re-export everything from index
2-
export * from './index';
2+
export * from "./index";
33
// Add browser-specific implementations or overrides here
4-
import { Buffer } from 'buffer';
5-
if (typeof window !== 'undefined') {
4+
import { Buffer } from "buffer";
5+
if (typeof window !== "undefined") {
66
window.Buffer = Buffer;
77
}
88
// Add any browser-specific initialization code here
9-
const isBrowser = typeof window !== 'undefined';
9+
const isBrowser = typeof window !== "undefined";
1010
if (isBrowser) {
1111
// Initialize any browser-specific features
12-
console.log('NostrNsecSeedphrase loaded in browser environment');
12+
console.log("NostrNsecSeedphrase loaded in browser environment");
1313
}

dist/browser/nostr-nsec-seedphrase.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/browser/nostr-nsec-seedphrase.min.js.LICENSE.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
99

10+
/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */
11+
12+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
13+
1014
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1115

1216
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */
17+
18+
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */

0 commit comments

Comments
 (0)