crypto-keygen-suite
Version:
Key generation utilities for cryptographic operations. YES I RENAMED IT. SIX STATE PROTOCOL!!! See its folder for all <3
106 lines (90 loc) • 3.84 kB
JavaScript
import yargs from 'yargs/yargs';
import { hideBin } from 'yargs/helpers';
import crypto from 'crypto';
class SignalProtocol {
constructor() {
this.rootKey = crypto.randomBytes(32);
this.chainKey = crypto.randomBytes(32);
this.sendRatchetKey = crypto.generateKeyPairSync('x25519');
this.recvRatchetKey = null;
this.sendHeaderKey = null;
this.recvHeaderKey = null;
this.sendMessageKey = null;
}
generateKeyPair() {
const { privateKey, publicKey } = crypto.generateKeyPairSync('x25519');
return { privateKey, publicKey: publicKey.export({ type: 'spki', format: 'pem' }) };
}
deriveKeys(sharedSecret) {
const hkdf = crypto.createHmac('sha256', sharedSecret)
.update('signal protocol')
.digest();
return {
messageKey: hkdf.slice(0, 32),
newChainKey: hkdf.slice(32)
};
}
encryptMessage(plaintext) {
if (!this.sendMessageKey) {
const derivedKeys = this.deriveKeys(this.chainKey);
this.sendMessageKey = derivedKeys.messageKey;
this.chainKey = derivedKeys.newChainKey;
}
const nonce = crypto.randomBytes(12);
const aesgcm = crypto.createCipheriv('aes-256-gcm', this.sendMessageKey, nonce);
const encrypted = Buffer.concat([aesgcm.update(plaintext, 'utf8'), aesgcm.final()]);
const authTag = aesgcm.getAuthTag();
return Buffer.concat([nonce, authTag, encrypted]).toString('base64');
}
}
// CLI Setup
async function main() {
const argv = yargs(hideBin(process.argv))
.option('mode', {
alias: 'm',
type: 'string',
choices: ['generate', 'encrypt'],
describe: 'Choose operation mode: generate keys or encrypt',
})
.option('message', {
alias: 'msg',
type: 'string',
describe: 'Message to encrypt',
})
.help()
.argv;
const signalProtocol = new SignalProtocol();
if (argv.mode === 'generate') {
const aliceKeys = signalProtocol.generateKeyPair();
const bobKeys = signalProtocol.generateKeyPair();
// Derive shared secrets
const aliceSharedSecret = crypto.diffieHellman({
privateKey: aliceKeys.privateKey,
publicKey: crypto.createPublicKey(bobKeys.publicKey)
});
const bobSharedSecret = crypto.diffieHellman({
privateKey: bobKeys.privateKey,
publicKey: crypto.createPublicKey(aliceKeys.publicKey)
});
// Derive keys from shared secret
const { messageKey, newChainKey } = signalProtocol.deriveKeys(aliceSharedSecret);
signalProtocol.rootKey = messageKey;
signalProtocol.chainKey = newChainKey;
console.log(`✅ Generated Signal Protocol Keys`);
console.log(`🔑 Alice's Private Key: ${aliceKeys.privateKey.export({ type: 'pkcs8', format: 'pem' })}`);
console.log(`📡 Alice's Public Key: ${aliceKeys.publicKey}`);
console.log(`🔑 Bob's Private Key: ${bobKeys.privateKey.export({ type: 'pkcs8', format: 'pem' })}`);
console.log(`📡 Bob's Public Key: ${bobKeys.publicKey}`);
} else if (argv.mode === 'encrypt') {
if (!argv.message) {
console.error("❌ Encryption requires a message");
return;
}
const encryptedMessage = signalProtocol.encryptMessage(argv.message);
console.log(`🔐 Encrypted Message (Base64): ${encryptedMessage}`);
} else {
console.error("❌ Invalid mode. Use --mode generate | encrypt");
}
}
console.log("🚀 Debug: Running main function...");
main();