UNPKG

@alessiofrittoli/crypto-cipher

Version:
2 lines (1 loc) 7.17 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);var _stream = require('stream');var _coercion = require('@alessiofrittoli/crypto-buffer/coercion');var t=class t{static encrypt(r,e,o={}){let a=_coercion.coerceToUint8Array.call(void 0, r),{salt:c,Key:s,IV:n,AAD:p,options:{algorithm:i,authTag:h}}=t.newKeyIV(e,o);if(t.isCBC(i)){let T=_crypto2.default.createCipheriv(i,s,n),d=Buffer.concat([T.update(a),T.final()]);return Buffer.concat([c,n,d])}let y=_crypto2.default.createCipheriv(i,s,n,{authTagLength:h});t.isCCM(i)&&y.setAAD(p,{plaintextLength:a.length}),(t.isGCM(i)||t.isOCB(i))&&y.setAAD(p);let u=Buffer.concat([y.update(a),y.final()]),l=y.getAuthTag();return Buffer.concat([c,n,p,l,u])}static decrypt(r,e,o={}){let a=_coercion.coerceToUint8Array.call(void 0, r),c=_coercion.coerceToUint8Array.call(void 0, e),s=t.resolveOptions(o),{algorithm:n}=s,p=a.subarray(0,s.salt);a=a.subarray(s.salt);let i=a.subarray(0,s.iv);a=a.subarray(s.iv);let h=_crypto2.default.scryptSync(c,p,s.length);if(t.isCBC(n)){let f=_crypto2.default.createDecipheriv(s.algorithm,h,i);return Buffer.concat([f.update(a),f.final()])}let y=s.aadLength,u=s.authTag,l=a.subarray(0,y);a=a.subarray(y);let T=a.subarray(0,u);a=a.subarray(u);let d=_crypto2.default.createDecipheriv(n,h,i,{authTagLength:u});return t.isCCM(n)&&d.setAAD(l,{plaintextLength:a.length}),(t.isGCM(n)||t.isOCB(n))&&d.setAAD(l),d.setAuthTag(T),Buffer.concat([d.update(a),d.final()])}static streamEncrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:o,IV:a,options:{input:c,output:s,algorithm:n,salt:p,iv:i,authTag:h}}=t.newKeyIV(r,e),y=t.encrypt(Buffer.concat([o,a]),r,{algorithm:n,salt:p,iv:i,authTag:h}),u=_crypto2.default.createCipheriv(n,o,a);return{cipher:u,encrypt:()=>t.stream({cipher:u,input:c,output:s,encryptedKey:y})}}static streamDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,salt:s,iv:n,authTag:p,length:i}=t.resolveOptions(e),h=i+n+s+n+p;return t.extractKeyIV(o,h).then(([y,u])=>{if(u.errored)throw u.errored;let l=t.decrypt(y,r,{algorithm:c,salt:s,iv:n,authTag:p}),T=l.subarray(0,i),d=l.subarray(i),f=_crypto2.default.createDecipheriv(c,T,d);return{decipher:f,decrypt:()=>t.decipherStream({decipher:f,input:u,output:a})}})}static hybridEncrypt(r,e,o){o.algorithm||(o.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:a,IV:c,options:{algorithm:s,input:n,output:p}}=t.newKeyIV(r,o),i=_crypto2.default.publicEncrypt(e,Buffer.concat([a,c])),h=_crypto2.default.createCipheriv(s,a,c);return{cipher:h,encrypt:()=>t.stream({cipher:h,input:n,output:p,encryptedKey:i})}}static hybridDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,length:s,rsaKeyLength:n}=t.resolveOptions(e);return t.extractKeyIV(o,n).then(([p,i])=>{let h=_crypto2.default.privateDecrypt(r,p),y=h.subarray(0,s),u=h.subarray(s),l=_crypto2.default.createDecipheriv(c,y,u);return{decipher:l,decrypt:()=>t.decipherStream({decipher:l,input:i,output:a})}})}static stream(r){let{cipher:e,encryptedKey:o,input:a,output:c}=r;return new Promise((s,n)=>{e.on("error",n),a.on("error",n),c.on("error",n),c.on("finish",s),c.write(o),a.pipe(e).pipe(c)})}static decipherStream(r){let{decipher:e,input:o,output:a}=r;return new Promise((c,s)=>{e.on("error",s),o.on("error",s),a.on("error",s),a.on("finish",c),o.pipe(e).pipe(a)})}static extractKeyIV(r,e){return new Promise((o,a)=>{let c=Buffer.alloc(0),s=0,n=!1,p=new (0, _stream.Transform)({async transform(i,h,y){if(c.length<e&&(c=Buffer.concat([c,i])),s+=i.length,c.length>e){let u=Math.max(0,c.length-e);c=c.subarray(0,e);let l=i.subarray(u*-1);return n||(o([c,this]),n=!0),this.push(l,h),y()}return s>e&&(n||(o([c,this]),n=!0),this.push(i,h)),y()},final(i){return c.length<e?i(new Error("The extracted KeyIV length is less than the expected length.")):i()}});p.on("error",a),r.on("error",i=>{p.destroy(i),a(i)}),r.pipe(p)})}static newKeyIV(r,e={}){let o=_coercion.coerceToUint8Array.call(void 0, r),a=t.resolveOptions(e),c=_crypto2.default.randomBytes(a.salt),s=_crypto2.default.scryptSync(o,c,a.length),n=_crypto2.default.randomBytes(a.iv),p=a.aad||_crypto2.default.scryptSync(s,c,a.aadLength);return{options:a,Key:s,IV:n,AAD:p,salt:c}}static resolveOptions(r={}){let e={...r};e.aad&&(e.aad=_coercion.coerceToUint8Array.call(void 0, e.aad)),e.salt||(e.salt=t.SALT_LENGTH.default),e.authTag||(e.authTag=t.AUTH_TAG_LENGTH.default),e.aadLength=_optionalChain([e, 'access', _ => _.aad, 'optionalAccess', _2 => _2.length])||e.aadLength||t.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,t.SALT_LENGTH.min),t.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,t.AUTH_TAG_LENGTH.min),t.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,t.AAD_LENGTH.min),t.AAD_LENGTH.max));let{keyLength:o,algorithm:a}=t.getKeyLength(r.algorithm);return e.algorithm=a,e.length=o,e.iv=t.getIVLength(a,r),e}static getIVLength(r=t.DEFAULT_ALGORITHM.buffer,e={}){switch(r){case"aes-128-ccm":case"aes-128-ocb":case"aes-192-ccm":case"aes-192-ocb":case"aes-256-ccm":case"aes-256-ocb":return 8;case"chacha20-poly1305":return 12;default:return Math.min(Math.max(e.iv||t.IV_LENGTH.default,t.IV_LENGTH.min),t.IV_LENGTH.max)}}static getKeyLength(r=t.DEFAULT_ALGORITHM.buffer){switch(r){case"chacha20-poly1305":return{algorithm:r,keyLength:256/8};case"aes-128-cbc":case"aes-128-ccm":case"aes-128-gcm":case"aes-128-ocb":return{algorithm:r,keyLength:128/8};case"aes-192-cbc":case"aes-192-ccm":case"aes-192-gcm":case"aes-192-ocb":return{algorithm:r,keyLength:192/8};case"aes-256-cbc":case"aes-256-ccm":case"aes-256-gcm":case"aes-256-ocb":default:return{algorithm:r,keyLength:256/8}}}static isGCM(r){return r==="aes-128-gcm"||r==="aes-192-gcm"||r==="aes-256-gcm"}static isCCM(r){return r==="aes-128-ccm"||r==="aes-192-ccm"||r==="aes-256-ccm"||r==="chacha20-poly1305"}static isOCB(r){return r==="aes-128-ocb"||r==="aes-192-ocb"||r==="aes-256-ocb"}static isCBC(r){return r==="aes-128-cbc"||r==="aes-192-cbc"||r==="aes-256-cbc"}};t.SALT_LENGTH={min:16,max:64,default:32},t.IV_LENGTH={min:8,max:32,default:16},t.AUTH_TAG_LENGTH={min:4,max:16,default:16},t.AAD_LENGTH={min:16,max:128,default:32},t.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},t.ALGORITHMS=["aes-128-cbc","aes-128-ccm","aes-128-gcm","aes-128-ocb","aes-192-cbc","aes-192-ccm","aes-192-gcm","aes-192-ocb","aes-256-cbc","aes-256-ccm","aes-256-gcm","aes-256-ocb","chacha20-poly1305"];var A=t;exports.Cipher = A;