@celo/cryptographic-utils
Advanced tools
Comparing version 5.0.6 to 5.0.7-beta.0
@@ -34,65 +34,2 @@ "use strict"; | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -103,12 +40,12 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.AccountUtils = exports.generateKeysFromSeed = exports.generateSeed = exports.generateDeterministicInviteCode = exports.generateKeys = exports.suggestMnemonicCorrections = exports.detectMnemonicLanguage = exports.mnemonicLengthFromStrength = exports.getAllLanguages = exports.formatNonAccentedCharacters = exports.normalizeMnemonic = exports.invalidMnemonicWords = exports.validateMnemonic = exports.generateMnemonic = exports.MnemonicStrength = exports.MnemonicLanguages = exports.CELO_DERIVATION_PATH_BASE = void 0; | ||
var account_1 = require("@celo/base/lib/account"); | ||
var string_1 = require("@celo/base/lib/string"); | ||
var address_1 = require("@celo/utils/lib/address"); | ||
var levenshtein_1 = require("@celo/utils/lib/levenshtein"); | ||
var bip32_1 = __importDefault(require("bip32")); | ||
var bip39 = __importStar(require("bip39")); | ||
var keccak_1 = require("ethereum-cryptography/keccak"); | ||
var utils_1 = require("ethereum-cryptography/utils"); | ||
var randombytes_1 = __importDefault(require("randombytes")); | ||
var ecc = __importStar(require("tiny-secp256k1")); | ||
const account_1 = require("@celo/base/lib/account"); | ||
const string_1 = require("@celo/base/lib/string"); | ||
const address_1 = require("@celo/utils/lib/address"); | ||
const levenshtein_1 = require("@celo/utils/lib/levenshtein"); | ||
const bip32_1 = __importDefault(require("bip32")); | ||
const bip39 = __importStar(require("bip39")); | ||
const keccak_1 = require("ethereum-cryptography/keccak"); | ||
const utils_1 = require("ethereum-cryptography/utils"); | ||
const randombytes_1 = __importDefault(require("randombytes")); | ||
const ecc = __importStar(require("tiny-secp256k1")); | ||
// Exports moved to @celo/base, forwarding them | ||
@@ -120,8 +57,8 @@ // here for backwards compatibility | ||
Object.defineProperty(exports, "MnemonicStrength", { enumerable: true, get: function () { return account_2.MnemonicStrength; } }); | ||
var bip32 = (0, bip32_1.default)(ecc); | ||
const bip32 = (0, bip32_1.default)(ecc); | ||
function defaultGenerateMnemonic(strength, rng, wordlist) { | ||
return new Promise(function (resolve, reject) { | ||
return new Promise((resolve, reject) => { | ||
strength = strength || 128; | ||
rng = rng || randombytes_1.default; | ||
rng(strength / 8, function (error, randomBytesBuffer) { | ||
rng(strength / 8, (error, randomBytesBuffer) => { | ||
if (error) { | ||
@@ -136,3 +73,3 @@ reject(error); | ||
} | ||
var bip39Wrapper = { | ||
const bip39Wrapper = { | ||
mnemonicToSeedSync: bip39.mnemonicToSeedSync, | ||
@@ -143,34 +80,18 @@ mnemonicToSeed: bip39.mnemonicToSeed, | ||
}; | ||
function generateMnemonic(strength, language, bip39ToUse) { | ||
if (strength === void 0) { strength = account_1.MnemonicStrength.s256_24words; } | ||
if (bip39ToUse === void 0) { bip39ToUse = bip39Wrapper; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, bip39ToUse.generateMnemonic(strength, undefined, getWordList(language))]; | ||
}); | ||
function generateMnemonic(strength = account_1.MnemonicStrength.s256_24words, language, bip39ToUse = bip39Wrapper) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return bip39ToUse.generateMnemonic(strength, undefined, getWordList(language)); | ||
}); | ||
} | ||
exports.generateMnemonic = generateMnemonic; | ||
function validateMnemonic(mnemonic, bip39ToUse, language) { | ||
var e_1, _a; | ||
if (bip39ToUse === void 0) { bip39ToUse = bip39Wrapper; } | ||
function validateMnemonic(mnemonic, bip39ToUse = bip39Wrapper, language) { | ||
if (language !== undefined) { | ||
return bip39ToUse.validateMnemonic(mnemonic, getWordList(language)); | ||
} | ||
var languages = getAllLanguages(); | ||
try { | ||
for (var languages_1 = __values(languages), languages_1_1 = languages_1.next(); !languages_1_1.done; languages_1_1 = languages_1.next()) { | ||
var guessedLanguage = languages_1_1.value; | ||
if (bip39ToUse.validateMnemonic(mnemonic, getWordList(guessedLanguage))) { | ||
return true; | ||
} | ||
const languages = getAllLanguages(); | ||
for (const guessedLanguage of languages) { | ||
if (bip39ToUse.validateMnemonic(mnemonic, getWordList(guessedLanguage))) { | ||
return true; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (languages_1_1 && !languages_1_1.done && (_a = languages_1.return)) _a.call(languages_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return false; | ||
@@ -187,9 +108,9 @@ } | ||
function invalidMnemonicWords(mnemonic, language) { | ||
var words = splitMnemonic(mnemonic); | ||
var detectedLanguage = language !== null && language !== void 0 ? language : detectMnemonicLanguage(words); | ||
const words = splitMnemonic(mnemonic); | ||
const detectedLanguage = language !== null && language !== void 0 ? language : detectMnemonicLanguage(words); | ||
if (detectedLanguage === undefined) { | ||
return undefined; | ||
} | ||
var wordSet = new Set(getWordList(detectedLanguage)); | ||
return words.filter(function (word) { return !wordSet.has(word); }); | ||
const wordSet = new Set(getWordList(detectedLanguage)); | ||
return words.filter((word) => !wordSet.has(word)); | ||
} | ||
@@ -205,5 +126,5 @@ exports.invalidMnemonicWords = invalidMnemonicWords; | ||
function normalizeMnemonic(mnemonic, language) { | ||
var words = splitMnemonic(mnemonic); | ||
var lowered = words.map(function (word) { return word.toLowerCase(); }); | ||
var detectedLanguage = language !== null && language !== void 0 ? language : detectMnemonicLanguage(lowered); | ||
const words = splitMnemonic(mnemonic); | ||
const lowered = words.map((word) => word.toLowerCase()); | ||
const detectedLanguage = language !== null && language !== void 0 ? language : detectMnemonicLanguage(lowered); | ||
// If the language is unknown, do not run further normalizations. | ||
@@ -225,5 +146,5 @@ if (detectedLanguage === undefined) { | ||
if (isLatinBasedLanguage(language)) { | ||
var wordList = getWordList(language); | ||
var normalizedWordMap_1 = new Map(wordList.map(function (word) { return [(0, string_1.normalizeAccents)(word), word]; })); | ||
return words.map(function (word) { var _a; return (_a = normalizedWordMap_1.get((0, string_1.normalizeAccents)(word))) !== null && _a !== void 0 ? _a : word; }); | ||
const wordList = getWordList(language); | ||
const normalizedWordMap = new Map(wordList.map((word) => [(0, string_1.normalizeAccents)(word), word])); | ||
return words.map((word) => { var _a; return (_a = normalizedWordMap.get((0, string_1.normalizeAccents)(word))) !== null && _a !== void 0 ? _a : word; }); | ||
} | ||
@@ -306,3 +227,3 @@ return words; | ||
function splitMnemonic(mnemonic) { | ||
return __spreadArray([], __read(mnemonic.trim().split(/\s+/)), false); | ||
return [...mnemonic.trim().split(/\s+/)]; | ||
} | ||
@@ -325,5 +246,5 @@ /** | ||
// Assign a match score to each language by how many words of the phrase are in each language. | ||
var scores = (candidates !== null && candidates !== void 0 ? candidates : getAllLanguages()).map(function (candidate) { | ||
var wordSet = new Set(getWordList(candidate)); | ||
var score = words.reduce(function (count, word) { return (wordSet.has(word) ? count + 1 : count); }, 0); | ||
const scores = (candidates !== null && candidates !== void 0 ? candidates : getAllLanguages()).map((candidate) => { | ||
const wordSet = new Set(getWordList(candidate)); | ||
const score = words.reduce((count, word) => (wordSet.has(word) ? count + 1 : count), 0); | ||
return [candidate, score]; | ||
@@ -333,5 +254,3 @@ }); | ||
// have the same score, but it likely to occur only for specially constructed phrases. | ||
var _a = __read(scores.reduce(function (_a, _b) { | ||
var _c = __read(_a, 2), leaders = _c[0], leadingScore = _c[1]; | ||
var _d = __read(_b, 2), candidate = _d[0], score = _d[1]; | ||
const [winners, highscore] = scores.reduce(([leaders, leadingScore], [candidate, score]) => { | ||
if (score > leadingScore) { | ||
@@ -341,6 +260,6 @@ return [[candidate], score]; | ||
else if (score === leadingScore) { | ||
return [__spreadArray(__spreadArray([], __read(leaders), false), [candidate], false), leadingScore]; | ||
return [[...leaders, candidate], leadingScore]; | ||
} | ||
return [leaders, leadingScore]; | ||
}, [[], 0]), 2), winners = _a[0], highscore = _a[1]; | ||
}, [[], 0]); | ||
if (winners.length !== 1 || highscore < 1) { | ||
@@ -374,52 +293,30 @@ return undefined; | ||
*/ | ||
function suggestMnemonicCorrections(mnemonic, language, strength) { | ||
var words, expectedLength, lang, _a, _b, suggestion, phrase, e_2_1; | ||
var e_2, _c; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
words = splitMnemonic(mnemonic); | ||
expectedLength = strength && mnemonicLengthFromStrength(strength); | ||
if ((expectedLength && words.length !== expectedLength) || words.length % 3 !== 0) { | ||
return [2 /*return*/]; | ||
} | ||
lang = language !== null && language !== void 0 ? language : detectMnemonicLanguage(words); | ||
if (lang === undefined) { | ||
return [2 /*return*/]; | ||
} | ||
_d.label = 1; | ||
case 1: | ||
_d.trys.push([1, 6, 7, 8]); | ||
_a = __values(suggestUnvalidatedCorrections(words, lang)), _b = _a.next(); | ||
_d.label = 2; | ||
case 2: | ||
if (!!_b.done) return [3 /*break*/, 5]; | ||
suggestion = _b.value; | ||
phrase = joinMnemonic(suggestion, lang); | ||
if (!validateMnemonic(phrase, undefined, lang)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, phrase]; | ||
case 3: | ||
_d.sent(); | ||
_d.label = 4; | ||
case 4: | ||
_b = _a.next(); | ||
return [3 /*break*/, 2]; | ||
case 5: return [3 /*break*/, 8]; | ||
case 6: | ||
e_2_1 = _d.sent(); | ||
e_2 = { error: e_2_1 }; | ||
return [3 /*break*/, 8]; | ||
case 7: | ||
try { | ||
if (_b && !_b.done && (_c = _a.return)) _c.call(_a); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
return [7 /*endfinally*/]; | ||
case 8: return [2 /*return*/]; | ||
function* suggestMnemonicCorrections(mnemonic, language, strength) { | ||
const words = splitMnemonic(mnemonic); | ||
// Function does not currently attempt to correct phrases with an incorrect number of words. | ||
const expectedLength = strength && mnemonicLengthFromStrength(strength); | ||
if ((expectedLength && words.length !== expectedLength) || words.length % 3 !== 0) { | ||
return; | ||
} | ||
// If the language is not provided or detected, no suggestions can be given. | ||
const lang = language !== null && language !== void 0 ? language : detectMnemonicLanguage(words); | ||
if (lang === undefined) { | ||
return; | ||
} | ||
// Iterate over the generator of corrections, and return those that have a valid checksum. | ||
for (const suggestion of suggestUnvalidatedCorrections(words, lang)) { | ||
const phrase = joinMnemonic(suggestion, lang); | ||
if (validateMnemonic(phrase, undefined, lang)) { | ||
yield phrase; | ||
} | ||
}); | ||
} | ||
} | ||
exports.suggestMnemonicCorrections = suggestMnemonicCorrections; | ||
/// Generates a list of suggested phases based on an edit distance correction heuristic. | ||
function suggestUnvalidatedCorrections(words, language) { | ||
function* suggestUnvalidatedCorrections(words, language) { | ||
// Create a list of suggestions for each word in the phrase. | ||
// Note that for valid words, the input word will be in the suggestions lists at edit distance 0. | ||
// Valid words are not considered separately because it's possible for an error to yield a valid | ||
// word, (e.g. "tent" mistyped as "rent", both of which are valid words) | ||
const spotSuggestions = words.map((word) => wordSuggestions(word, language)); | ||
// Combine the given suggestions lists to produce all combinations with weight, defined as the sum | ||
@@ -429,141 +326,44 @@ // edit distances for all chosen words, equal to the given weight value. | ||
// yielded with any other given weight. | ||
function combineSuggestions(suggestionsLists, weight) { | ||
var suggestions, remaining, _a, _b, distance, _c, _d, list, _e, _f, suggestion, e_4_1, e_5_1, e_6_1; | ||
var e_6, _g, e_5, _h, e_4, _j; | ||
var _k, _l, _m; | ||
return __generator(this, function (_o) { | ||
switch (_o.label) { | ||
case 0: | ||
if (suggestionsLists.length < 1 || weight < 0) { | ||
throw Error('programming error: suggestions map must have at least one entry'); | ||
} | ||
suggestions = suggestionsLists[0]; | ||
if (!(suggestionsLists.length === 1)) return [3 /*break*/, 2]; | ||
return [5 /*yield**/, __values((_l = (_k = suggestions.get(weight)) === null || _k === void 0 ? void 0 : _k.map(function (suggestion) { return [suggestion]; })) !== null && _l !== void 0 ? _l : [])]; | ||
case 1: | ||
_o.sent(); | ||
return [2 /*return*/]; | ||
case 2: | ||
remaining = __spreadArray([], __read(suggestionsLists.slice(1)), false); | ||
_o.label = 3; | ||
case 3: | ||
_o.trys.push([3, 20, 21, 22]); | ||
_a = __values(__spreadArray([], __read(suggestions.keys()), false).sort()), _b = _a.next(); | ||
_o.label = 4; | ||
case 4: | ||
if (!!_b.done) return [3 /*break*/, 19]; | ||
distance = _b.value; | ||
if (distance > weight) { | ||
return [3 /*break*/, 19]; | ||
} | ||
_o.label = 5; | ||
case 5: | ||
_o.trys.push([5, 16, 17, 18]); | ||
_c = (e_5 = void 0, __values(combineSuggestions(remaining, weight - distance))), _d = _c.next(); | ||
_o.label = 6; | ||
case 6: | ||
if (!!_d.done) return [3 /*break*/, 15]; | ||
list = _d.value; | ||
_o.label = 7; | ||
case 7: | ||
_o.trys.push([7, 12, 13, 14]); | ||
_e = (e_4 = void 0, __values((_m = suggestions.get(distance)) !== null && _m !== void 0 ? _m : [])), _f = _e.next(); | ||
_o.label = 8; | ||
case 8: | ||
if (!!_f.done) return [3 /*break*/, 11]; | ||
suggestion = _f.value; | ||
return [4 /*yield*/, __spreadArray([suggestion], __read(list), false)]; | ||
case 9: | ||
_o.sent(); | ||
_o.label = 10; | ||
case 10: | ||
_f = _e.next(); | ||
return [3 /*break*/, 8]; | ||
case 11: return [3 /*break*/, 14]; | ||
case 12: | ||
e_4_1 = _o.sent(); | ||
e_4 = { error: e_4_1 }; | ||
return [3 /*break*/, 14]; | ||
case 13: | ||
try { | ||
if (_f && !_f.done && (_j = _e.return)) _j.call(_e); | ||
} | ||
finally { if (e_4) throw e_4.error; } | ||
return [7 /*endfinally*/]; | ||
case 14: | ||
_d = _c.next(); | ||
return [3 /*break*/, 6]; | ||
case 15: return [3 /*break*/, 18]; | ||
case 16: | ||
e_5_1 = _o.sent(); | ||
e_5 = { error: e_5_1 }; | ||
return [3 /*break*/, 18]; | ||
case 17: | ||
try { | ||
if (_d && !_d.done && (_h = _c.return)) _h.call(_c); | ||
} | ||
finally { if (e_5) throw e_5.error; } | ||
return [7 /*endfinally*/]; | ||
case 18: | ||
_b = _a.next(); | ||
return [3 /*break*/, 4]; | ||
case 19: return [3 /*break*/, 22]; | ||
case 20: | ||
e_6_1 = _o.sent(); | ||
e_6 = { error: e_6_1 }; | ||
return [3 /*break*/, 22]; | ||
case 21: | ||
try { | ||
if (_b && !_b.done && (_g = _a.return)) _g.call(_a); | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
return [7 /*endfinally*/]; | ||
case 22: return [2 /*return*/]; | ||
function* combineSuggestions(suggestionsLists, weight) { | ||
var _a, _b, _c; | ||
if (suggestionsLists.length < 1 || weight < 0) { | ||
throw Error('programming error: suggestions map must have at least one entry'); | ||
} | ||
const suggestions = suggestionsLists[0]; | ||
// Base case: When there is only one entry, "consume" the rest of the weight by yielding all | ||
// words in the suggestions list at edit distance `weight` as singleton lists (i.e. 1 word | ||
// phrases). | ||
if (suggestionsLists.length === 1) { | ||
yield* (_b = (_a = suggestions.get(weight)) === null || _a === void 0 ? void 0 : _a.map((suggestion) => [suggestion])) !== null && _b !== void 0 ? _b : []; | ||
return; | ||
} | ||
// Recursion case: When more than one entry exists, consume iteratively 0 to weight units and | ||
// combine it with all arrays of the remaining weight, generated from removing one entry. | ||
const remaining = [...suggestionsLists.slice(1)]; | ||
for (const distance of [...suggestions.keys()].sort()) { | ||
if (distance > weight) { | ||
break; | ||
} | ||
}); | ||
} | ||
var spotSuggestions, weight, _a, _b, suggestedWords, e_3_1; | ||
var e_3, _c; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
spotSuggestions = words.map(function (word) { | ||
return wordSuggestions(word, language); | ||
}); | ||
weight = 0; | ||
_d.label = 1; | ||
case 1: | ||
if (!(weight < 1000)) return [3 /*break*/, 10]; | ||
_d.label = 2; | ||
case 2: | ||
_d.trys.push([2, 7, 8, 9]); | ||
_a = (e_3 = void 0, __values(combineSuggestions(spotSuggestions, weight))), _b = _a.next(); | ||
_d.label = 3; | ||
case 3: | ||
if (!!_b.done) return [3 /*break*/, 6]; | ||
suggestedWords = _b.value; | ||
return [4 /*yield*/, suggestedWords]; | ||
case 4: | ||
_d.sent(); | ||
_d.label = 5; | ||
case 5: | ||
_b = _a.next(); | ||
return [3 /*break*/, 3]; | ||
case 6: return [3 /*break*/, 9]; | ||
case 7: | ||
e_3_1 = _d.sent(); | ||
e_3 = { error: e_3_1 }; | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
try { | ||
if (_b && !_b.done && (_c = _a.return)) _c.call(_a); | ||
for (const list of combineSuggestions(remaining, weight - distance)) { | ||
for (const suggestion of (_c = suggestions.get(distance)) !== null && _c !== void 0 ? _c : []) { | ||
yield [suggestion, ...list]; | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
return [7 /*endfinally*/]; | ||
case 9: | ||
weight++; | ||
return [3 /*break*/, 1]; | ||
case 10: return [2 /*return*/]; | ||
} | ||
} | ||
}); | ||
} | ||
// Increase the weight counter incrementally. At each weight, all returned suggestions are | ||
// considered equally probably. All suggestions of a higher weight are disjoint from and | ||
// considered less probably than all suggestions of a lower weight. | ||
// Note that the stopping condition is chosen arbitrarily to be weight of 1000. In practice, the | ||
// number of strings with weight less than 1000 is exponentially large and impossible to generate. | ||
// The stopping condition is included to eventually break when handle malformed phrases. | ||
// | ||
// TODO(victor) In the current formulation, only integral weights can be handled, and it is | ||
// inefficeint to loop over weights that cannot be constructed. Ideally this should be corrected | ||
// to allow for non-integral weights. | ||
for (let weight = 0; weight < 1000; weight++) { | ||
for (const suggestedWords of combineSuggestions(spotSuggestions, weight)) { | ||
yield suggestedWords; | ||
} | ||
} | ||
} | ||
@@ -574,7 +374,6 @@ // Given a word and lnaguage, returns a map of all words in the BIP-39 word list for the given | ||
return getWordList(language) | ||
.map(function (word) { return ({ distance: (0, levenshtein_1.levenshteinDistance)(typo, word), word: word }); }) | ||
.reduce(function (map, _a) { | ||
var distance = _a.distance, word = _a.word; | ||
.map((word) => ({ distance: (0, levenshtein_1.levenshteinDistance)(typo, word), word })) | ||
.reduce((map, { distance, word }) => { | ||
// Reduction uses mutation, instead of spread, as an optimization. | ||
var list = map.get(distance); | ||
const list = map.get(distance); | ||
if (list !== undefined) { | ||
@@ -589,17 +388,6 @@ list.push(word); | ||
} | ||
function generateKeys(mnemonic, password, changeIndex, addressIndex, bip39ToUse, derivationPath) { | ||
if (changeIndex === void 0) { changeIndex = 0; } | ||
if (addressIndex === void 0) { addressIndex = 0; } | ||
if (bip39ToUse === void 0) { bip39ToUse = bip39Wrapper; } | ||
if (derivationPath === void 0) { derivationPath = account_1.CELO_DERIVATION_PATH_BASE; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var seed; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, generateSeed(mnemonic, password, bip39ToUse)]; | ||
case 1: | ||
seed = _a.sent(); | ||
return [2 /*return*/, generateKeysFromSeed(seed, changeIndex, addressIndex, derivationPath)]; | ||
} | ||
}); | ||
function generateKeys(mnemonic, password, changeIndex = 0, addressIndex = 0, bip39ToUse = bip39Wrapper, derivationPath = account_1.CELO_DERIVATION_PATH_BASE) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const seed = yield generateSeed(mnemonic, password, bip39ToUse); | ||
return generateKeysFromSeed(seed, changeIndex, addressIndex, derivationPath); | ||
}); | ||
@@ -609,7 +397,4 @@ } | ||
// XXX: (@soloseng) no test for this function? | ||
function generateDeterministicInviteCode(recipientPhoneHash, recipientPepper, addressIndex, changeIndex, derivationPath) { | ||
if (addressIndex === void 0) { addressIndex = 0; } | ||
if (changeIndex === void 0) { changeIndex = 0; } | ||
if (derivationPath === void 0) { derivationPath = account_1.CELO_DERIVATION_PATH_BASE; } | ||
var seed = (0, keccak_1.keccak256)((0, utils_1.utf8ToBytes)(recipientPhoneHash + recipientPepper)); | ||
function generateDeterministicInviteCode(recipientPhoneHash, recipientPepper, addressIndex = 0, changeIndex = 0, derivationPath = account_1.CELO_DERIVATION_PATH_BASE) { | ||
const seed = (0, keccak_1.keccak256)((0, utils_1.utf8ToBytes)(recipientPhoneHash + recipientPepper)); | ||
return generateKeysFromSeed(seed, changeIndex, addressIndex, derivationPath); | ||
@@ -620,29 +405,17 @@ } | ||
// It was added only because a backwards compatibility bug | ||
function generateSeed(mnemonic, password, bip39ToUse, keyByteLength) { | ||
if (bip39ToUse === void 0) { bip39ToUse = bip39Wrapper; } | ||
if (keyByteLength === void 0) { keyByteLength = 64; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var seed, bufAux; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, bip39ToUse.mnemonicToSeed(mnemonic, password)]; | ||
case 1: | ||
seed = _a.sent(); | ||
if (keyByteLength > 0 && seed.byteLength > keyByteLength) { | ||
bufAux = Buffer.allocUnsafe(keyByteLength); | ||
seed.copy(bufAux, 0, 0, keyByteLength); | ||
seed = bufAux; | ||
} | ||
return [2 /*return*/, seed]; | ||
} | ||
}); | ||
function generateSeed(mnemonic, password, bip39ToUse = bip39Wrapper, keyByteLength = 64) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let seed = yield bip39ToUse.mnemonicToSeed(mnemonic, password); | ||
if (keyByteLength > 0 && seed.byteLength > keyByteLength) { | ||
const bufAux = Buffer.allocUnsafe(keyByteLength); | ||
seed.copy(bufAux, 0, 0, keyByteLength); | ||
seed = bufAux; | ||
} | ||
return seed; | ||
}); | ||
} | ||
exports.generateSeed = generateSeed; | ||
function generateKeysFromSeed(seed, changeIndex, addressIndex, derivationPath) { | ||
if (changeIndex === void 0) { changeIndex = 0; } | ||
if (addressIndex === void 0) { addressIndex = 0; } | ||
if (derivationPath === void 0) { derivationPath = account_1.CELO_DERIVATION_PATH_BASE; } | ||
var node = bip32.fromSeed(seed); | ||
var newNode = node.derivePath("".concat(derivationPath ? "".concat(derivationPath, "/") : '').concat(changeIndex, "/").concat(addressIndex)); | ||
function generateKeysFromSeed(seed, changeIndex = 0, addressIndex = 0, derivationPath = account_1.CELO_DERIVATION_PATH_BASE) { | ||
const node = bip32.fromSeed(seed); | ||
const newNode = node.derivePath(`${derivationPath ? `${derivationPath}/` : ''}${changeIndex}/${addressIndex}`); | ||
if (!newNode.privateKey) { | ||
@@ -660,12 +433,12 @@ // As we are generating the node from a seed, the node will always have a private key and this would never happened | ||
exports.AccountUtils = { | ||
detectMnemonicLanguage: detectMnemonicLanguage, | ||
generateMnemonic: generateMnemonic, | ||
normalizeMnemonic: normalizeMnemonic, | ||
validateMnemonic: validateMnemonic, | ||
invalidMnemonicWords: invalidMnemonicWords, | ||
suggestMnemonicCorrections: suggestMnemonicCorrections, | ||
generateKeys: generateKeys, | ||
generateSeed: generateSeed, | ||
generateKeysFromSeed: generateKeysFromSeed, | ||
detectMnemonicLanguage, | ||
generateMnemonic, | ||
normalizeMnemonic, | ||
validateMnemonic, | ||
invalidMnemonicWords, | ||
suggestMnemonicCorrections, | ||
generateKeys, | ||
generateSeed, | ||
generateKeysFromSeed, | ||
}; | ||
//# sourceMappingURL=account.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getBlsPoP = exports.getBlsPublicKey = exports.blsPrivateKeyToProcessedPrivateKey = exports.BLS_POP_SIZE = exports.BLS_PUBLIC_KEY_SIZE = void 0; | ||
var bls12377js_1 = require("@celo/bls12377js"); | ||
const bls12377js_1 = require("@celo/bls12377js"); | ||
// this is an implementation of a subset of BLS12-377 | ||
var address_1 = require("@celo/utils/lib/address"); | ||
var keccak_1 = require("ethereum-cryptography/keccak"); | ||
var BigInteger = require('bigi'); | ||
var reverse = require('buffer-reverse'); | ||
var n = BigInteger.fromHex('12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001', 16); | ||
var MODULUSMASK = 31; | ||
const address_1 = require("@celo/utils/lib/address"); | ||
const keccak_1 = require("ethereum-cryptography/keccak"); | ||
const BigInteger = require('bigi'); | ||
const reverse = require('buffer-reverse'); | ||
const n = BigInteger.fromHex('12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001', 16); | ||
const MODULUSMASK = 31; | ||
exports.BLS_PUBLIC_KEY_SIZE = 96; | ||
exports.BLS_POP_SIZE = 48; | ||
var blsPrivateKeyToProcessedPrivateKey = function (privateKeyHex) { | ||
for (var i = 0; i < 256; i++) { | ||
var originalPrivateKeyBytes = Buffer.from(privateKeyHex, 'hex'); | ||
var iBuffer = Buffer.alloc(1); | ||
const blsPrivateKeyToProcessedPrivateKey = (privateKeyHex) => { | ||
for (let i = 0; i < 256; i++) { | ||
const originalPrivateKeyBytes = Buffer.from(privateKeyHex, 'hex'); | ||
const iBuffer = Buffer.alloc(1); | ||
iBuffer[0] = i; | ||
var keyBytes = Buffer.concat([ | ||
const keyBytes = Buffer.concat([ | ||
Buffer.from('ecdsatobls', 'utf8'), | ||
@@ -24,10 +24,10 @@ iBuffer, | ||
]); | ||
var privateKeyBLSBytes = (0, keccak_1.keccak256)(keyBytes); | ||
// tslint:disable-next-line:no-bitwise | ||
const privateKeyBLSBytes = (0, keccak_1.keccak256)(keyBytes); | ||
// eslint-disable-next-line no-bitwise | ||
privateKeyBLSBytes[0] &= MODULUSMASK; | ||
var privateKeyNum = BigInteger.fromBuffer(privateKeyBLSBytes); | ||
const privateKeyNum = BigInteger.fromBuffer(privateKeyBLSBytes); | ||
if (privateKeyNum.compareTo(n) >= 0) { | ||
continue; | ||
} | ||
var privateKeyBytes = reverse(privateKeyNum.toBuffer()); | ||
const privateKeyBytes = reverse(privateKeyNum.toBuffer()); | ||
return privateKeyBytes; | ||
@@ -38,16 +38,16 @@ } | ||
exports.blsPrivateKeyToProcessedPrivateKey = blsPrivateKeyToProcessedPrivateKey; | ||
var getBlsPrivateKey = function (privateKeyHex) { | ||
var blsPrivateKeyBytes = (0, exports.blsPrivateKeyToProcessedPrivateKey)(privateKeyHex.slice(2)); | ||
const getBlsPrivateKey = (privateKeyHex) => { | ||
const blsPrivateKeyBytes = (0, exports.blsPrivateKeyToProcessedPrivateKey)(privateKeyHex.slice(2)); | ||
return blsPrivateKeyBytes; | ||
}; | ||
var getBlsPublicKey = function (privateKeyHex) { | ||
var blsPrivateKeyBytes = getBlsPrivateKey(privateKeyHex); | ||
const getBlsPublicKey = (privateKeyHex) => { | ||
const blsPrivateKeyBytes = getBlsPrivateKey(privateKeyHex); | ||
return '0x' + bls12377js_1.BLS.privateToPublicBytes(blsPrivateKeyBytes).toString('hex'); | ||
}; | ||
exports.getBlsPublicKey = getBlsPublicKey; | ||
var getBlsPoP = function (address, privateKeyHex) { | ||
const getBlsPoP = (address, privateKeyHex) => { | ||
if (!(0, address_1.isValidAddress)(address)) { | ||
throw new Error('Invalid checksum address for generating BLS proof-of-possession'); | ||
} | ||
var blsPrivateKeyBytes = getBlsPrivateKey(privateKeyHex); | ||
const blsPrivateKeyBytes = getBlsPrivateKey(privateKeyHex); | ||
return ('0x' + bls12377js_1.BLS.signPoP(blsPrivateKeyBytes, Buffer.from(address.slice(2), 'hex')).toString('hex')); | ||
@@ -54,0 +54,0 @@ }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CommentEncryptionUtils = exports.decryptComment = exports.encryptComment = exports.decryptData = exports.encryptData = void 0; | ||
var ecies_1 = require("@celo/utils/lib/ecies"); | ||
var crypto_1 = require("crypto"); | ||
var dataEncryptionKey_1 = require("./dataEncryptionKey"); | ||
var ECIES_SESSION_KEY_LEN = 129; | ||
var MIN_COMMENT_KEY_LENGTH = 33; | ||
var TAG = 'CommentEncryption'; | ||
const ecies_1 = require("@celo/utils/lib/ecies"); | ||
const crypto_1 = require("crypto"); | ||
const dataEncryptionKey_1 = require("./dataEncryptionKey"); | ||
const ECIES_SESSION_KEY_LEN = 129; | ||
const MIN_COMMENT_KEY_LENGTH = 33; | ||
const TAG = 'CommentEncryption'; | ||
/** | ||
@@ -19,6 +19,6 @@ * Encrypts a buffer to two recipients. Throws on error. | ||
function encryptData(data, pubKeyRecipient, pubKeySelf) { | ||
var sessionKey = (0, crypto_1.randomBytes)(16); | ||
var sessionKeyToSelf = (0, ecies_1.Encrypt)(pubKeySelf, sessionKey); | ||
var sessionKeyToOther = (0, ecies_1.Encrypt)(pubKeyRecipient, sessionKey); | ||
var ciphertext = (0, ecies_1.AES128EncryptAndHMAC)(sessionKey, sessionKey, data); | ||
const sessionKey = (0, crypto_1.randomBytes)(16); | ||
const sessionKeyToSelf = (0, ecies_1.Encrypt)(pubKeySelf, sessionKey); | ||
const sessionKeyToOther = (0, ecies_1.Encrypt)(pubKeyRecipient, sessionKey); | ||
const ciphertext = (0, ecies_1.AES128EncryptAndHMAC)(sessionKey, sessionKey, data); | ||
return Buffer.concat([sessionKeyToOther, sessionKeyToSelf, ciphertext]); | ||
@@ -40,7 +40,7 @@ } | ||
} | ||
var sessionKeyEncrypted = sender | ||
const sessionKeyEncrypted = sender | ||
? data.slice(ECIES_SESSION_KEY_LEN, ECIES_SESSION_KEY_LEN * 2) | ||
: data.slice(0, ECIES_SESSION_KEY_LEN); | ||
var sessionKey = (0, ecies_1.Decrypt)(key, sessionKeyEncrypted); | ||
var encryptedMessage = data.slice(ECIES_SESSION_KEY_LEN * 2); | ||
const sessionKey = (0, ecies_1.Decrypt)(key, sessionKeyEncrypted); | ||
const encryptedMessage = data.slice(ECIES_SESSION_KEY_LEN * 2); | ||
return (0, ecies_1.AES128DecryptAndHMAC)(sessionKey, sessionKey, encryptedMessage); | ||
@@ -66,5 +66,5 @@ } | ||
// Uncompress public keys & strip out the leading 0x04 | ||
var pubRecip = (0, dataEncryptionKey_1.decompressPublicKey)(pubKeyRecipient); | ||
var pubSelf = (0, dataEncryptionKey_1.decompressPublicKey)(pubKeySelf); | ||
var data = encryptData(Buffer.from(comment, 'ucs2'), pubRecip, pubSelf).toString('base64'); | ||
const pubRecip = (0, dataEncryptionKey_1.decompressPublicKey)(pubKeyRecipient); | ||
const pubSelf = (0, dataEncryptionKey_1.decompressPublicKey)(pubKeySelf); | ||
const data = encryptData(Buffer.from(comment, 'ucs2'), pubRecip, pubSelf).toString('base64'); | ||
return { | ||
@@ -76,4 +76,4 @@ success: true, | ||
catch (e) { | ||
console.info("".concat(TAG, "/Error encrypting comment: ").concat(e)); | ||
return { success: false, comment: comment }; | ||
console.info(`${TAG}/Error encrypting comment: ${e}`); | ||
return { success: false, comment }; | ||
} | ||
@@ -93,9 +93,9 @@ } | ||
try { | ||
var buf = Buffer.from(comment, 'base64'); | ||
var data = decryptData(buf, key, sender).toString('ucs2'); | ||
const buf = Buffer.from(comment, 'base64'); | ||
const data = decryptData(buf, key, sender).toString('ucs2'); | ||
return { success: true, comment: data }; | ||
} | ||
catch (error) { | ||
console.info("".concat(TAG, "/Could not decrypt: ").concat(error.message)); | ||
return { success: false, comment: comment }; | ||
console.info(`${TAG}/Could not decrypt: ${error.message}`); | ||
return { success: false, comment }; | ||
} | ||
@@ -105,5 +105,5 @@ } | ||
exports.CommentEncryptionUtils = { | ||
encryptComment: encryptComment, | ||
decryptComment: decryptComment, | ||
encryptComment, | ||
decryptComment, | ||
}; | ||
//# sourceMappingURL=commentEncryption.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DataEncryptionKeyUtils = exports.deriveDek = exports.decompressPublicKey = exports.compressedPubKey = void 0; | ||
var address_1 = require("@celo/utils/lib/address"); | ||
var account_1 = require("./account"); | ||
const address_1 = require("@celo/utils/lib/address"); | ||
const account_1 = require("./account"); | ||
/** | ||
@@ -16,5 +16,5 @@ * Turns a private key to a compressed public key (hex string with hex leader). | ||
// tslint:disable-next-line:import-blacklist | ||
var EC = require('elliptic').ec; | ||
var ec = new EC('secp256k1'); | ||
var key = ec.keyFromPrivate(privateKey); | ||
const EC = require('elliptic').ec; | ||
const ec = new EC('secp256k1'); | ||
const key = ec.keyFromPrivate(privateKey); | ||
return (0, address_1.ensureLeading0x)(key.getPublic(true, 'hex')); | ||
@@ -34,4 +34,4 @@ } | ||
// tslint:disable-next-line:import-blacklist | ||
var EC = require('elliptic').ec; | ||
var ec = new EC('secp256k1'); | ||
const EC = require('elliptic').ec; | ||
const ec = new EC('secp256k1'); | ||
return Buffer.from(ec.keyFromPublic(publicKey).getPublic(false, 'hex'), 'hex').slice(1); | ||
@@ -55,6 +55,6 @@ } | ||
exports.DataEncryptionKeyUtils = { | ||
compressedPubKey: compressedPubKey, | ||
decompressPublicKey: decompressPublicKey, | ||
deriveDek: deriveDek, | ||
compressedPubKey, | ||
decompressPublicKey, | ||
deriveDek, | ||
}; | ||
//# sourceMappingURL=dataEncryptionKey.js.map |
{ | ||
"name": "@celo/cryptographic-utils", | ||
"version": "5.0.6", | ||
"version": "5.0.7-beta.0", | ||
"description": "Some Celo utils for comment/data encryption, bls, and mnemonics", | ||
@@ -11,11 +11,11 @@ "author": "Celo", | ||
"homepage": "https://celo-sdk-docs.readthedocs.io/en/latest/cryptographic-utils", | ||
"repository": "https://github.com/celo-org/celo-monorepo/tree/master/packages/sdk/cryptographic-utils", | ||
"repository": "https://github.com/celo-org/developer-tooling/tree/master/packages/sdk/cryptographic-utils", | ||
"scripts": { | ||
"prepublishOnly": "yarn build", | ||
"build": "tsc -b .", | ||
"docs": "typedoc", | ||
"docs": "yarn run --top-level typedoc", | ||
"clean": "tsc -b . --clean", | ||
"test": "jest --runInBand --ci", | ||
"test:verbose": "jest --verbose", | ||
"lint": "tslint -c tslint.json --project ." | ||
"test": "yarn run --top-level jest --runInBand --ci", | ||
"test:verbose": "yarn run --top-level jest --verbose", | ||
"lint": "yarn run --top-level eslint -c .eslintrc.js " | ||
}, | ||
@@ -26,5 +26,5 @@ "files": [ | ||
"dependencies": { | ||
"@celo/utils": "^5.0.6", | ||
"@celo/base": "^6.0.0", | ||
"@celo/bls12377js": "0.1.1", | ||
"@celo/base": "^6.0.0", | ||
"@celo/utils": "^6.0.0-beta.0", | ||
"@ethereumjs/util": "8.0.5", | ||
@@ -37,3 +37,3 @@ "@types/bn.js": "^5.1.0", | ||
"bip32": "^3.1.0", | ||
"bip39": "https://github.com/bitcoinjs/bip39#d8ea080a18b40f301d4e2219a2991cd2417e83c2", | ||
"bip39": "https://github.com/bitcoinjs/bip39#a7ecbfe2e60d0214ce17163d610cad9f7b23140c", | ||
"buffer-reverse": "^1.0.1", | ||
@@ -40,0 +40,0 @@ "elliptic": "^6.5.4", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
HTTP dependency
Supply chain riskContains a dependency which resolves to a remote HTTP URL which could be used to inject untrusted code and reduce overall package reliability.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
HTTP dependency
Supply chain riskContains a dependency which resolves to a remote HTTP URL which could be used to inject untrusted code and reduce overall package reliability.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
59246
831
2
+ Added@celo/utils@6.0.1(transitive)
+ Added@ethereumjs/util@8.1.0(transitive)
+ Added@noble/curves@1.4.2(transitive)
+ Added@noble/hashes@1.4.0(transitive)
+ Added@scure/bip32@1.4.0(transitive)
+ Added@scure/bip39@1.3.0(transitive)
+ Addedethereum-cryptography@2.2.1(transitive)
+ Addedmicro-ftch@0.3.1(transitive)
+ Addedweb3-eth-abi@1.10.4(transitive)
+ Addedweb3-utils@1.10.4(transitive)
- Removed@celo/utils@5.0.6(transitive)
- Removed@types/pbkdf2@3.1.2(transitive)
- Removed@types/secp256k1@4.0.6(transitive)
- Removedblakejs@1.2.1(transitive)
- Removedbn.js@4.11.9(transitive)
- Removedbrowserify-aes@1.2.0(transitive)
- Removedbuffer-xor@1.0.3(transitive)
- Removedethereum-cryptography@0.1.3(transitive)
- Removedethereumjs-util@7.1.5(transitive)
- Removedevp_bytestokey@1.0.3(transitive)
- Removedkeccak@3.0.4(transitive)
- Removednode-addon-api@2.0.25.1.0(transitive)
- Removednode-gyp-build@4.8.2(transitive)
- Removedpbkdf2@3.1.2(transitive)
- Removedscrypt-js@3.0.1(transitive)
- Removedsecp256k1@4.0.4(transitive)
- Removedsetimmediate@1.0.5(transitive)
- Removedweb3-eth-abi@1.10.0(transitive)
- Removedweb3-utils@1.10.0(transitive)
Updated@celo/utils@^6.0.0-beta.0
Updatedbip39@https://github.com/bitcoinjs/bip39#a7ecbfe2e60d0214ce17163d610cad9f7b23140c