All files / ethers.js/src.ts/wallet json-crowdsale.ts

100% Statements 74/74
100% Branches 6/6
100% Functions 2/2
100% Lines 74/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 4x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 384x 384x 6x 6x 6x  
/**
 *  @_subsection: api/wallet:JSON Wallets  [json-wallets]
 */
 
import { CBC, pkcs7Strip } from "aes-js";
 
import { getAddress } from "../address/index.js";
import { pbkdf2 } from "../crypto/index.js";
import { id } from "../hash/index.js";
import { getBytes, assertArgument } from "../utils/index.js";
 
import { getPassword, looseArrayify, spelunk } from "./utils.js";
 
 
/**
 *  The data stored within a JSON Crowdsale wallet is fairly
 *  minimal.
 */
export type CrowdsaleAccount = {
    privateKey: string;
    address: string;
}
 
/**
 *  Returns true if %%json%% is a valid JSON Crowdsale wallet.
 */
export function isCrowdsaleJson(json: string): boolean {
    try {
        const data = JSON.parse(json);
        if (data.encseed) { return true; }
    } catch (error) { }
    return false;
}
 
// See: https://github.com/ethereum/pyethsaletool
 
/**
 *  Before Ethereum launched, it was necessary to create a wallet
 *  format for backers to use, which would be used to receive ether
 *  as a reward for contributing to the project.
 *
 *  The [[link-crowdsale]] format is now obsolete, but it is still
 *  useful to support and the additional code is fairly trivial as
 *  all the primitives required are used through core portions of
 *  the library.
 */
export function decryptCrowdsaleJson(json: string, _password: string | Uint8Array): CrowdsaleAccount {
    const data = JSON.parse(json);
    const password = getPassword(_password);
 
    // Ethereum Address
    const address = getAddress(spelunk(data, "ethaddr:string!"));
 
    // Encrypted Seed
    const encseed = looseArrayify(spelunk(data, "encseed:string!"));
    assertArgument(encseed && (encseed.length % 16) === 0, "invalid encseed", "json", json);
 
    const key = getBytes(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);
 
    const iv = encseed.slice(0, 16);
    const encryptedSeed = encseed.slice(16);
 
    // Decrypt the seed
    const aesCbc = new CBC(key, iv);
    const seed = pkcs7Strip(getBytes(aesCbc.decrypt(encryptedSeed)));
 
    // This wallet format is weird... Convert the binary encoded hex to a string.
    let seedHex = "";
    for (let i = 0; i < seed.length; i++) {
        seedHex += String.fromCharCode(seed[i]);
    }
 
    return { address, privateKey: id(seedHex) };
}