UNPKG

crypt4gh_js

Version:
91 lines (85 loc) 3.65 kB
import * as helperfunction from './helper functions.js' import * as generateKeyPair from '@stablelib/x25519' import scrypt from 'scrypt-js' import _sodium from 'libsodium-wrappers' import { Buffer } from 'buffer' const magicBytestring = helperfunction.string2byte('c4gh-v1') // without passphrase const kdfNoneBestring = helperfunction.string2byte('none') const chiperNoneBytestring = helperfunction.string2byte('none') // with pasphrase const kdfScript = helperfunction.string2byte('scrypt') const chiperChacha = helperfunction.string2byte('chacha20_poly1305') /** * Main function for key generation * @param {*} pasphrase => optional parameter, password (string) * @returns => List of secret key content and public key content */ export async function keygen (pasphrase) { try { const keys = generateKeyPair.generateKeyPair() const pubkeyFile = createPubkey(keys.publicKey) const seckeyFile = await createSeckey(keys.secretKey, pasphrase) return [seckeyFile, pubkeyFile] } catch (e) { console.trace('Key generation not possible.') } } /** * Function to create public key contents * @param {*} pubkey => public key (Uint8array of length 32) * @returns => pubkey content as string */ export function createPubkey (pubkey) { try { const b64 = btoa(String.fromCharCode.apply(null, pubkey)) return '-----BEGIN CRYPT4GH PUBLIC KEY-----\n' + b64 + '\n-----END CRYPT4GH PUBLIC KEY-----\n' } catch (e) { console.trace('Pubkey generation not possible.') } } /** * Function to create secret key contents * @param {*} seckey => secret key (Uint8array of length 32) * @param {*} passphrase => optional parameter, string to encrypt secret key * @returns => seckey content as string */ export async function createSeckey (seckey, passphrase) { try { let a = '' await (async () => { await _sodium.ready const sodium = _sodium if (passphrase) { if (passphrase.replace(/\s+/g, '') === '') { throw new Error('Password can not be empty string') } const salt = sodium.randombytes_buf(16) const saltround = new Uint8Array(4 + salt.length) saltround.set([0, 0, 0, 0]) saltround.set(salt, 4) const N = 16384; const r = 8; const p = 1 const dklen = 32 const keyPrmoise = scrypt.scrypt(helperfunction.string2byte(passphrase), salt, N, r, p, dklen) const key = keyPrmoise.then(function (result) { const nonce = sodium.randombytes_buf(12) const decData = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(seckey, null, null, nonce, result) const decNonce = Buffer.concat([magicBytestring, new Uint8Array([0, 6]), kdfScript, new Uint8Array([0, 20]), saltround, new Uint8Array([0, 17]), chiperChacha, new Uint8Array([0, 12 + decData.length]), nonce, decData]) const x = new Uint8Array(decNonce) const b64 = btoa(String.fromCharCode.apply(null, x)) return '-----BEGIN CRYPT4GH PRIVATE KEY-----\n' + b64 + '\n-----END CRYPT4GH PRIVATE KEY-----\n' }) a = await key } else { const decNonce = Buffer.concat([magicBytestring, new Uint8Array([0, 4]), kdfNoneBestring, new Uint8Array([0, 4]), chiperNoneBytestring, new Uint8Array([0, 32]), seckey]) const x = new Uint8Array(decNonce) const b64 = btoa(String.fromCharCode.apply(null, x)) a = '-----BEGIN CRYPT4GH PRIVATE KEY-----\n' + b64 + '\n-----END CRYPT4GH PRIVATE KEY-----\n' } })() return a } catch (e) { console.trace('Secret key generation not possible.') throw new Error('Password can not be empty string') } }