ethers.js/packages/json-wallets/src.ts/crowdsale.ts

80 lines
2.4 KiB
TypeScript
Raw Permalink Normal View History

2019-05-14 18:25:46 -04:00
"use strict";
import aes from "aes-js";
import { ExternallyOwnedAccount } from "@ethersproject/abstract-signer";
import { getAddress } from "@ethersproject/address";
import { arrayify, Bytes } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/keccak256";
import { pbkdf2 } from "@ethersproject/pbkdf2";
import { toUtf8Bytes } from "@ethersproject/strings";
import { Description } from "@ethersproject/properties";
2019-08-01 18:04:06 -04:00
import { Logger } from "@ethersproject/logger";
import { version } from "./_version";
const logger = new Logger(version);
2019-05-14 18:25:46 -04:00
import { getPassword, looseArrayify, searchPath } from "./utils";
2020-04-25 01:06:28 -04:00
export interface _CrowdsaleAccount {
2020-01-07 19:47:55 -05:00
address: string;
privateKey: string;
_isCrowdsaleAccount: boolean;
}
export class CrowdsaleAccount extends Description<_CrowdsaleAccount> implements ExternallyOwnedAccount {
2019-05-14 18:25:46 -04:00
readonly address: string;
readonly privateKey: string;
readonly mnemonic?: string;
readonly path?: string;
readonly _isCrowdsaleAccount: boolean;
isCrowdsaleAccount(value: any): value is CrowdsaleAccount {
return !!(value && value._isCrowdsaleAccount);
2019-05-14 18:25:46 -04:00
}
}
// See: https://github.com/ethereum/pyethsaletool
export function decrypt(json: string, password: Bytes | string): ExternallyOwnedAccount {
const data = JSON.parse(json);
2019-05-14 18:25:46 -04:00
password = getPassword(password);
// Ethereum Address
const ethaddr = getAddress(searchPath(data, "ethaddr"));
2019-05-14 18:25:46 -04:00
// Encrypted Seed
const encseed = looseArrayify(searchPath(data, "encseed"));
2019-05-14 18:25:46 -04:00
if (!encseed || (encseed.length % 16) !== 0) {
2019-08-01 18:04:06 -04:00
logger.throwArgumentError("invalid encseed", "json", json);
2019-05-14 18:25:46 -04:00
}
const key = arrayify(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);
2019-05-14 18:25:46 -04:00
const iv = encseed.slice(0, 16);
const encryptedSeed = encseed.slice(16);
2019-05-14 18:25:46 -04:00
// Decrypt the seed
const aesCbc = new aes.ModeOfOperation.cbc(key, iv);
const seed = aes.padding.pkcs7.strip(arrayify(aesCbc.decrypt(encryptedSeed)));
2019-05-14 18:25:46 -04:00
// 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]);
}
const seedHexBytes = toUtf8Bytes(seedHex);
2019-05-14 18:25:46 -04:00
const privateKey = keccak256(seedHexBytes);
2019-05-14 18:25:46 -04:00
return new CrowdsaleAccount ({
_isCrowdsaleAccount: true,
2019-05-14 18:25:46 -04:00
address: ethaddr,
privateKey: privateKey
});
}