Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
// @flow
import { randomBytes, secretbox } from 'tweetnacl'
import { encodeUTF8, decodeUTF8, encodeBase64, decodeBase64 } from 'tweetnacl-util'
const NONCE_LEN = secretbox.nonceLength
const KEY_LEN = secretbox.keyLength
type Utf8 = string
type Base64 = string
const generateCredentials: () => { nonce: Uint8Array, key: Uint8Array }
= () => ({
nonce: randomBytes(NONCE_LEN),
key: randomBytes(KEY_LEN),
})
const join: (Uint8Array, Uint8Array) => Uint8Array
= (a, b) => {
const c = new Uint8Array(a.length + b.length)
c.set(a)
c.set(b, a.length)
create: async (paperKeys: string, password: string): boolean => {
const keyUnit8 = SHA256(password);
const seedHexUnit8 = TextEncoding.toUnit8(PaperKey.toSeedHex(paperKeys));
const nonce = await randomBytes(secretbox.nonceLength);
const vault = await secretbox(seedHexUnit8, nonce, keyUnit8);
// eslint-disable-next-line no-return-await
return await Vault.save('seed', {
nonce: Base64.encode(nonce),
vault: Base64.encode(vault),
});
},
.then(key => {
let minLength =
naclSecretbox.overheadLength + naclSecretbox.nonceLength;
if (encryptedData.length < minLength) {
throw new Error(
'encrypted payload too short',
);
}
let parts = encryptedData.split(':');
if (parts.length != 3) {
throw new Error('unexpected data format');
}
let nonce = decodeBase64(parts[1]);
let cipherText = decodeBase64(parts[2]);
let bytes = naclSecretbox.open(cipherText, nonce, key);
if (bytes === null) {
throw new Error('probably invalid key');
encrypt: async (entry: string, seed: string): string => {
const seedMD5Unit8 = SHA256(seed);
const nonce = randomBytes(secretbox.nonceLength);
const entryUint8 = TextEncoding.toUnit8(entry);
const box = await secretbox(entryUint8, nonce, seedMD5Unit8);
const encSecret = new Uint8Array(nonce.length + box.length);
encSecret.set(nonce);
encSecret.set(box, nonce.length);
return Base64.encode(encSecret);
},
decode (buf: Buffer): { ip: string, ts: Date } {
if (buf.length <= secretbox.nonceLength) {
throw new Error('Invalid SourceToken buffer to decode')
}
const nonce = buf.slice(buf.length - secretbox.nonceLength)
const data = secretbox.open(buf.slice(0, buf.length - secretbox.nonceLength), nonce, this.key)
if (data == null) {
throw new Error('SourceToken verify failured')
}
const captures = ASN1.parseDERWithTemplate(
Buffer.from(data.buffer as ArrayBuffer, data.byteOffset, data.length), tokenValidator)
return {
ip: bytesToIP(captures.ip.bytes),
ts: new Date((captures.ts.value as number) * 1000),
}
}
}
export const decrypt = (messageWithNonce, key) => {
const keyUint8Array = decodeBase64(key);
const messageWithNonceAsUint8Array = decodeBase64(messageWithNonce);
const nonce = messageWithNonceAsUint8Array.slice(0, secretbox.nonceLength);
const message = messageWithNonceAsUint8Array.slice(
secretbox.nonceLength,
messageWithNonce.length
);
const decrypted = secretbox.open(message, nonce, keyUint8Array);
if (!decrypted) {
throw new Error('Could not decrypt message');
}
const base64DecryptedMessage = encodeUTF8(decrypted);
return JSON.parse(base64DecryptedMessage);
};
export const decrypt = (messageWithNonce, key) => {
const keyUint8Array = decodeBase64(key);
const messageWithNonceAsUint8Array = decodeBase64(messageWithNonce);
const nonce = messageWithNonceAsUint8Array.slice(0, secretbox.nonceLength);
const message = messageWithNonceAsUint8Array.slice(
secretbox.nonceLength,
messageWithNonce.length
);
const decrypted = secretbox.open(message, nonce, keyUint8Array);
if (!decrypted) {
throw new Error('Could not decrypt message');
}
const base64DecryptedMessage = encodeUTF8(decrypted);
return JSON.parse(base64DecryptedMessage);
};
decode (buf: Buffer): { ip: string, ts: Date } {
if (buf.length <= secretbox.nonceLength) {
throw new Error('Invalid SourceToken buffer to decode')
}
const nonce = buf.slice(buf.length - secretbox.nonceLength)
const data = secretbox.open(buf.slice(0, buf.length - secretbox.nonceLength), nonce, this.key)
if (data == null) {
throw new Error('SourceToken verify failured')
}
const captures = ASN1.parseDERWithTemplate(
Buffer.from(data.buffer as ArrayBuffer, data.byteOffset, data.length), tokenValidator)
return {
ip: bytesToIP(captures.ip.bytes),
ts: new Date((captures.ts.value as number) * 1000),
}
}
}
const newNonce = () => randomBytes(secretbox.nonceLength);
decrypt: async (box: string, seed: string): string => {
const seedMD5Unit8 = SHA256(seed);
const boxUint8 = Base64.decode(box);
const nonce = new Uint8Array(Array.prototype.slice.call(boxUint8, 0, secretbox.nonceLength));
const message = new Uint8Array(Array.prototype.slice.call(boxUint8, secretbox.nonceLength, box.length));
const plainSecret = secretbox.open(message, nonce, seedMD5Unit8);
if (!plainSecret) {
return false;
}
return TextEncoding.toString(plainSecret);
},
};