json-crowdsale.ts 2.2 KB

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