-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1918 from dedis/work-fe1-ljankoschek-poptoken-mne…
…monic Work fe1 ljankoschek poptoken mnemonic
- Loading branch information
Showing
23 changed files
with
580 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { randomInt, createHash } from 'crypto'; | ||
|
||
import base64url from 'base64url'; | ||
import * as bip39 from 'bip39'; | ||
|
||
import { Base64UrlData } from 'core/objects'; | ||
|
||
/** | ||
* This function computes the hashcode of a buffer according to the | ||
* Java Arrays.hashcode(bytearray) function to get the same results as in fe2. | ||
* @param buf | ||
* @returns computed hash code as a number | ||
*/ | ||
function hashCode(buf: Buffer): number { | ||
if (buf === null) { | ||
return 0; | ||
} | ||
let result = 1; | ||
for (let element of buf) { | ||
if (element >= 2 ** 7) { | ||
element -= 2 ** 8; | ||
} | ||
result = 31 * result + (element == null ? 0 : element); | ||
result %= 2 ** 32; | ||
if (result >= 2 ** 31) { | ||
result -= 2 ** 32; | ||
} | ||
if (result < -(2 ** 31)) { | ||
result += 2 ** 32; | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* This function converts a buffer into mnemomic words from the english dictionary. | ||
* @param data buffer containing a base64 string | ||
* @returns array containing the mnemonic words | ||
*/ | ||
function generateMnemonic(data: Buffer): string[] { | ||
try { | ||
const digest = createHash('sha256').update(data).digest(); | ||
let mnemonic = ''; | ||
bip39.setDefaultWordlist('english'); | ||
mnemonic = bip39.entropyToMnemonic(digest); | ||
return mnemonic.split(' ').filter((word) => word.length > 0); | ||
} catch (e) { | ||
console.error( | ||
`Error generating the mnemonic for the base64 string ${base64url.encode(data)}`, | ||
e, | ||
); | ||
return []; | ||
} | ||
} | ||
|
||
/** | ||
* This function converts a buffer of a base64 string into a given number of mnemonic words. | ||
* | ||
* Disclaimer: there's no guarantee that different base64 inputs map to 2 different words. The | ||
* reason is that the representation space is limited. However, since the amount of messages is | ||
* low is practically improbable to have conflicts | ||
* | ||
* @param data Buffer of a base64 string | ||
* @param numberOfWords number of mnemonic words we want to generate | ||
* @return given number of mnemonic words concatenated with ' ' | ||
*/ | ||
function generateMnemonicFromBase64(data: Buffer, numberOfWords: number): string { | ||
// Generate the mnemonic words from the input data | ||
const mnemonicWords = generateMnemonic(data); | ||
if (mnemonicWords.length === 0) { | ||
return 'none'; | ||
} | ||
|
||
let result = ''; | ||
const hc = hashCode(data); | ||
for (let i = 0; i < numberOfWords; i += 1) { | ||
const wordIndex = Math.abs(hc + i) % mnemonicWords.length; | ||
result = `${result} ${mnemonicWords[wordIndex]}`; | ||
} | ||
|
||
return result.substring(1, result.length); | ||
} | ||
|
||
/** | ||
* This function filters all non digits characters and returns the first nbDigits | ||
* @param b64 base64 string containing numbers | ||
* @param nbDigits numbers of digitis to extract from input | ||
* @return string containing all the extracted numbers | ||
*/ | ||
function getFirstNumberDigits(b64: string, nbDigits: number): string { | ||
const digits = b64.replace(/\D/g, ''); | ||
return digits.slice(0, nbDigits).padStart(nbDigits, '0'); | ||
} | ||
|
||
/** | ||
* This function generates a unique and memorable username from a base64 string. | ||
* | ||
* @param input base64 string. | ||
* @return a username composed of truncated mnemonic words and a numerical suffix. | ||
*/ | ||
export function generateUsernameFromBase64(input: string): string { | ||
const words = generateMnemonicFromBase64(new Base64UrlData(input).toBuffer(), 2).split(' '); | ||
if (words.length < 2) { | ||
return `defaultUsername${randomInt(0, 10000000).toString().padStart(4, '0')}`; | ||
} | ||
const number = getFirstNumberDigits(input, 4); | ||
const word1 = words[0].charAt(0).toUpperCase() + words[0].slice(1); | ||
const word2 = words[1].charAt(0).toUpperCase() + words[1].slice(1); | ||
return `${word1}${word2}${number}`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { generateUsernameFromBase64 } from '../Mnemonic'; | ||
|
||
test('generateUsernameFromBase64 should generate the correct username for the token: d_xeXEsurEnyWOp04mrrMxC3m4cS-3jK_9_Aw-UYfww=', () => { | ||
const popToken = 'd_xeXEsurEnyWOp04mrrMxC3m4cS-3jK_9_Aw-UYfww='; | ||
const result = 'SpoonIssue0434'; | ||
expect(generateUsernameFromBase64(popToken)).toBe(result); | ||
}); | ||
|
||
test('generateUsernameFromBase64 should generate the correct username for the token: e5YJ5Q6x39u_AIK78_puEE2X5wy7Y7iYZLeuZx1lnZI=', () => { | ||
const popToken = 'e5YJ5Q6x39u_AIK78_puEE2X5wy7Y7iYZLeuZx1lnZI='; | ||
const result = 'BidTrial5563'; | ||
expect(generateUsernameFromBase64(popToken)).toBe(result); | ||
}); | ||
|
||
test('generateUsernameFromBase64 should generate the correct username for the token: Y5ZAd_7Ba31uu4EUIYbG2AVnthR623-NdPyYhtyechE=', () => { | ||
const popToken = 'Y5ZAd_7Ba31uu4EUIYbG2AVnthR623-NdPyYhtyechE='; | ||
const result = 'FigureDevote5731'; | ||
expect(generateUsernameFromBase64(popToken)).toBe(result); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.