@meeco/cryppo
Version:
In-browser encryption and decryption. Clone of Ruby Cryppo
95 lines • 4.05 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DerivedKeyOptions = exports.KeyDerivationStrategy = void 0;
const node_forge_1 = __importDefault(require("node-forge"));
const encoding_versions_js_1 = require("../encoding-versions.js");
const encryption_key_js_1 = require("../encryption-key.js");
const serialization_versions_js_1 = require("../serialization-versions.js");
const util_js_1 = require("../util.js");
const { md, pkcs5, random } = node_forge_1.default;
/**
* Most of these values are copied directly from the Ruby library
*/
const MIN_ITERATIONS = 20000;
const DEFAULT_LENGTH = 32;
const DEFAULT_ITERATION_VARIANCE = 10;
const DEFAULT_SALT_LENGTH = 20;
var KeyDerivationStrategy;
(function (KeyDerivationStrategy) {
KeyDerivationStrategy["Pbkdf2Hmac"] = "Pbkdf2Hmac";
})(KeyDerivationStrategy || (exports.KeyDerivationStrategy = KeyDerivationStrategy = {}));
/**
* Store configuration used for password based key derivation and
* serialize/de-serialize it.
*/
class DerivedKeyOptions {
static usesDerivedKey(serialized) {
const parts = serialized.split('.');
if (parts[parts.length - 2] === KeyDerivationStrategy.Pbkdf2Hmac) {
return true;
}
return false;
}
static randomFromOptions({ iterationVariance = DEFAULT_ITERATION_VARIANCE, length = DEFAULT_LENGTH, minIterations = MIN_ITERATIONS, strategy = KeyDerivationStrategy.Pbkdf2Hmac, useSalt, }) {
const variance = Math.floor(minIterations * (iterationVariance / 100));
const iterations = minIterations + Math.floor(Math.random() * variance);
const salt = useSalt || random.getBytesSync(DEFAULT_SALT_LENGTH);
return new DerivedKeyOptions({
strategy,
iterations,
salt,
length,
});
}
static fromSerialized(serialized) {
const { derivationStrategy, serializationArtifacts } = (0, util_js_1.deSerializeDerivedKeyOptions)(serialized);
return new DerivedKeyOptions({
// keys taken from ruby lib
strategy: derivationStrategy,
salt: (0, util_js_1.bytesBufferToBinaryString)(serializationArtifacts.iv),
iterations: serializationArtifacts.i,
length: serializationArtifacts.l,
hash: serializationArtifacts.hash,
...serializationArtifacts,
});
}
salt;
iterations;
length;
strategy;
hash;
constructor(options) {
this.salt = options.salt;
this.iterations = options.iterations;
this.length = options.length;
this.strategy = options.strategy;
this.hash = options.hash || 'SHA256';
}
serialize(serializationVersion = serialization_versions_js_1.SerializationFormat.latest_version) {
// keys taken from ruby lib
return (0, util_js_1.serializeDerivedKeyOptions)(this.strategy, {
iv: (0, util_js_1.binaryStringToBytesBuffer)(this.salt),
i: this.iterations,
l: this.length,
hash: this.hash,
}, serializationVersion);
}
deriveKey(key, encodingVersion = encoding_versions_js_1.EncodingVersions.latest_version) {
const hash = this.hash.toLocaleLowerCase();
const digest = md[hash].create();
key = encodingVersion === encoding_versions_js_1.EncodingVersions.legacy ? key : (0, util_js_1.encodeUtf8)(key);
return new Promise((resolve, reject) => {
return pkcs5.pbkdf2(key, this.salt, this.iterations, this.length, digest, (err, derivedKey) => {
if (err) {
return reject(err);
}
resolve(encryption_key_js_1.EncryptionKey.fromBytes((0, util_js_1.binaryStringToBytes)(derivedKey)));
});
});
}
}
exports.DerivedKeyOptions = DerivedKeyOptions;
//# sourceMappingURL=derived-key.js.map