- Add GETTING_STARTED.md with quick start guide and development modes - Add INSTALL.sh automated installation script - Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md - Add QUICK_REFERENCE.md for common commands - Add SETUP_GUIDE.md with detailed setup instructions - Update README.md with improved project overview - Add did-wallet app dependencies and node_modules
79 lines
2.8 KiB
JavaScript
79 lines
2.8 KiB
JavaScript
import { ed25519 } from '@noble/curves/ed25519';
|
|
import { sha256 } from '@noble/hashes/sha256';
|
|
import { concatBytes, randomBytes } from '@noble/hashes/utils';
|
|
import { base64 } from '@scure/base';
|
|
import * as P from 'micro-packed';
|
|
export const SSHString = P.string(P.U32BE);
|
|
export const SSHBuf = P.bytes(P.U32BE);
|
|
export const SSHKeyType = P.magic(SSHString, 'ssh-ed25519');
|
|
export const PublicKey = P.struct({ keyType: SSHKeyType, pubKey: P.bytes(P.U32BE) });
|
|
const PrivateKey = P.padRight(8, P.struct({
|
|
check1: P.bytes(4),
|
|
check2: P.bytes(4),
|
|
keyType: SSHKeyType,
|
|
pubKey: SSHBuf,
|
|
privKey: SSHBuf,
|
|
comment: SSHString,
|
|
}), (i) => i + 1);
|
|
// https://tools.ietf.org/html/draft-miller-ssh-agent-02#section-4.5
|
|
export const AuthData = P.struct({
|
|
nonce: SSHBuf,
|
|
userAuthRequest: P.U8, // == 50
|
|
user: SSHString,
|
|
conn: SSHString,
|
|
auth: SSHString,
|
|
haveSig: P.U8, // == 1
|
|
keyType: SSHKeyType,
|
|
pubKey: P.prefix(P.U32BE, PublicKey),
|
|
});
|
|
export const PrivateExport = P.base64armor('openssh private key', 70, P.struct({
|
|
magic: P.magicBytes('openssh-key-v1\0'),
|
|
// Only decrypted ed25519 keys supported for now
|
|
ciphername: P.magic(SSHString, 'none'),
|
|
kdfname: P.magic(SSHString, 'none'),
|
|
kdfopts: P.magic(SSHString, ''),
|
|
keys: P.array(P.U32BE, P.struct({
|
|
pubKey: P.prefix(P.U32BE, PublicKey),
|
|
privKey: P.prefix(P.U32BE, PrivateKey),
|
|
})),
|
|
}));
|
|
export function formatPublicKey(bytes, comment) {
|
|
const blob = PublicKey.encode({ pubKey: bytes });
|
|
return `ssh-ed25519 ${base64.encode(blob)}${comment ? ` ${comment}` : ''}`;
|
|
}
|
|
export function getFingerprint(bytes) {
|
|
const blob = PublicKey.encode({ pubKey: bytes });
|
|
// ssh-keygen -l -f ~/.ssh/id_ed25519
|
|
// 256 SHA256:+WK/Sl4XJjoxDlAWYuhq4Fl2hka9j3GOUjYczQkqnCI user@comp.local (ED25519)
|
|
return `SHA256:${base64.encode(sha256(blob)).replace(/=$/, '')}`;
|
|
}
|
|
// For determenistic generation in tests
|
|
export async function getKeys(privateKey, comment, checkBytes = randomBytes(4)) {
|
|
const pubKey = await ed25519.getPublicKey(privateKey);
|
|
return {
|
|
publicKeyBytes: pubKey,
|
|
publicKey: formatPublicKey(pubKey, comment),
|
|
fingerprint: getFingerprint(pubKey),
|
|
privateKey: PrivateExport.encode({
|
|
keys: [
|
|
{
|
|
pubKey: { pubKey },
|
|
privKey: {
|
|
// Check bytes, should be same
|
|
check1: checkBytes,
|
|
check2: checkBytes,
|
|
pubKey,
|
|
privKey: concatBytes(privateKey, pubKey),
|
|
comment: comment || '',
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
};
|
|
}
|
|
// For SSH Agents
|
|
export function authSign(privateKey, data) {
|
|
return ed25519.sign(AuthData.encode(data), privateKey);
|
|
}
|
|
export default getKeys;
|