Updated
This commit is contained in:
@@ -5,11 +5,24 @@
|
|||||||
* - The g1wallet namespace and session object are declared.
|
* - The g1wallet namespace and session object are declared.
|
||||||
* - The unlock button is wired — it intercepts the click but does NOT derive keys yet.
|
* - The unlock button is wired — it intercepts the click but does NOT derive keys yet.
|
||||||
* - The event API stubs are in place for cry01 and poll01 to listen to.
|
* - The event API stubs are in place for cry01 and poll01 to listen to.
|
||||||
* - scrypt-js is loaded (vendor/scrypt-js-3.0.1.min.js) but not yet called.
|
* - bip39 is loaded (vendor/bip39-3.1.0.min.js, English wordlist only) for
|
||||||
|
* mnemonic validation and entropy extraction, but full key derivation is
|
||||||
|
* not yet called.
|
||||||
|
*
|
||||||
|
* DERIVATION (not yet implemented — see RFC 0015):
|
||||||
|
* Per Duniter HD Wallet RFC 0015 (Dubp_HD_Wallet, git.duniter.org/documents/rfcs),
|
||||||
|
* the wallet's keypair is derived from a 12-word BIP39 mnemonic (English
|
||||||
|
* wordlist). The mnemonic's ENTROPY (16 bytes for 12 words) — not a PBKDF2
|
||||||
|
* seed — is the input to a BIP32-Ed25519 derivation (Khovratovich/Law
|
||||||
|
* construction, same family as Cardano's HD wallets).
|
||||||
|
*
|
||||||
|
* The exact BIP32-Ed25519 derivation path used by Ğecko/Cesium2 has not yet
|
||||||
|
* been confirmed against RFC 0015 and MUST be verified before this stub is
|
||||||
|
* replaced with real derivation code. Do not implement against assumptions.
|
||||||
*
|
*
|
||||||
* CRITICAL RULES (never relax these):
|
* CRITICAL RULES (never relax these):
|
||||||
* - The private key NEVER leaves the browser.
|
* - The private key NEVER leaves the browser.
|
||||||
* - The pseudo and password NEVER leave the browser.
|
* - The mnemonic NEVER leaves the browser.
|
||||||
* - No key material in localStorage, sessionStorage, or cookies.
|
* - No key material in localStorage, sessionStorage, or cookies.
|
||||||
* - The private key object is marked non-extractable in WebCrypto.
|
* - The private key object is marked non-extractable in WebCrypto.
|
||||||
* - One document, one confirmation, one click — no batch signing.
|
* - One document, one confirmation, one click — no batch signing.
|
||||||
@@ -68,7 +81,8 @@
|
|||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: implement signing via SubtleCrypto.sign() with Ed25519.
|
// TODO: implement signing via SubtleCrypto.sign() with Ed25519,
|
||||||
|
// using the key derived per RFC 0015 (BIP32-Ed25519 over mnemonic entropy).
|
||||||
// The signed bytes are base64-encoded and dispatched via the callback event.
|
// The signed bytes are base64-encoded and dispatched via the callback event.
|
||||||
console.warn('[g1wallet] requestSignature: signing not yet implemented.');
|
console.warn('[g1wallet] requestSignature: signing not yet implemented.');
|
||||||
}
|
}
|
||||||
@@ -125,20 +139,41 @@
|
|||||||
if (!unlockBtn) return; // Not on the wallet page.
|
if (!unlockBtn) return; // Not on the wallet page.
|
||||||
|
|
||||||
unlockBtn.addEventListener('click', function () {
|
unlockBtn.addEventListener('click', function () {
|
||||||
var pseudo = (document.getElementById('g1wallet-pseudo') || {}).value || '';
|
var mnemonicEl = document.getElementById('g1wallet-mnemonic');
|
||||||
var password = (document.getElementById('g1wallet-password') || {}).value || '';
|
var mnemonic = (mnemonicEl || {}).value || '';
|
||||||
|
|
||||||
|
// Normalize whitespace: collapse multiple spaces/newlines to single spaces, trim.
|
||||||
|
mnemonic = mnemonic.trim().replace(/\s+/g, ' ').toLowerCase();
|
||||||
|
|
||||||
_clearError();
|
_clearError();
|
||||||
|
|
||||||
if (!pseudo || !password) {
|
if (!mnemonic) {
|
||||||
_showError('Both pseudo and password are required.');
|
_showError('Mnemonic phrase is required.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: call scrypt derivation here.
|
var words = mnemonic.split(' ');
|
||||||
// scrypt(pseudo, password, N=4096, r=16, p=1) → 32-byte seed → Ed25519 keypair
|
if (words.length !== 12) {
|
||||||
// For now: log and show a placeholder message.
|
_showError('Mnemonic phrase must be exactly 12 words. You entered ' + words.length + '.');
|
||||||
console.log('[g1wallet] Unlock clicked. Derivation not yet implemented.');
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate against the BIP39 English wordlist and checksum.
|
||||||
|
if (window.bip39 && typeof window.bip39.validateMnemonic === 'function') {
|
||||||
|
if (!window.bip39.validateMnemonic(mnemonic)) {
|
||||||
|
_showError('Invalid mnemonic phrase. Check the words and try again.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_showError('Mnemonic validation library not available. Please reload the page.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: derive keypair from mnemonic entropy per RFC 0015 (BIP32-Ed25519).
|
||||||
|
// var entropy = window.bip39.mnemonicToEntropy(mnemonic);
|
||||||
|
// ... BIP32-Ed25519 derivation (path TBD, pending RFC 0015 confirmation) ...
|
||||||
|
// ... resulting Ed25519 keypair imported as non-extractable CryptoKey ...
|
||||||
|
console.log('[g1wallet] Unlock clicked. Mnemonic validated. Derivation not yet implemented.');
|
||||||
|
|
||||||
if (spinner) spinner.style.display = 'inline';
|
if (spinner) spinner.style.display = 'inline';
|
||||||
unlockBtn.disabled = true;
|
unlockBtn.disabled = true;
|
||||||
@@ -147,7 +182,7 @@
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (spinner) spinner.style.display = 'none';
|
if (spinner) spinner.style.display = 'none';
|
||||||
unlockBtn.disabled = false;
|
unlockBtn.disabled = false;
|
||||||
_showError('Key derivation not yet implemented. This is a skeleton build.');
|
_showError('Mnemonic is valid. Key derivation not yet implemented. This is a skeleton build.');
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,11 +191,9 @@
|
|||||||
_lockWallet();
|
_lockWallet();
|
||||||
if (lockedView) lockedView.style.display = '';
|
if (lockedView) lockedView.style.display = '';
|
||||||
if (unlockedView) unlockedView.style.display = 'none';
|
if (unlockedView) unlockedView.style.display = 'none';
|
||||||
// Clear credential fields.
|
// Clear the mnemonic field.
|
||||||
var pseudoEl = document.getElementById('g1wallet-pseudo');
|
var mnemonicEl = document.getElementById('g1wallet-mnemonic');
|
||||||
var passwordEl = document.getElementById('g1wallet-password');
|
if (mnemonicEl) mnemonicEl.value = '';
|
||||||
if (pseudoEl) pseudoEl.value = '';
|
|
||||||
if (passwordEl) passwordEl.value = '';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user