{"id":770,"date":"2020-12-25T06:31:56","date_gmt":"2020-12-25T06:31:56","guid":{"rendered":"https:\/\/www.wispwisp.com\/?p=770"},"modified":"2021-04-06T16:00:23","modified_gmt":"2021-04-06T16:00:23","slug":"how-metamask-stores-your-wallet-secret","status":"publish","type":"post","link":"https:\/\/www.wispwisp.com\/index.php\/2020\/12\/25\/how-metamask-stores-your-wallet-secret\/","title":{"rendered":"How MetaMask\ud83e\udd8a stores your wallet secret?"},"content":{"rendered":"\n<p>As a security engineer\/pentester in the blockchain space, I have tested many crypto wallet applications during research and client engagements. After seeing different ways of handing secrets in different wallets, I was curious about how MetaMask, one of the most famous crypto wallets in the space, does it. Well, if you ask me why I didn&#8217;t look at MetaMask earlier, because I just assume it&#8217;s secure, and the chance for me to find any issue is very low. <\/p>\n\n\n\n<p>Both their&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/MetaMask\/metamask-extension\" target=\"_blank\">Extension<\/a>&nbsp;and&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\" target=\"_blank\">Mobile app<\/a>&nbsp;along with many other modules create by MetaMask used in the application are open source. The codebase is by far the biggest among all crypto wallets I have seen. But it&#8217;s not too difficult to follow, as the code is well written and full of comments. <\/p>\n\n\n\n<p>The article goes by explaining different components in the app that relate to the secret storage. At the end of the article, I include a very rough code path that describes how the extension to create a new wallet. Note that Wallet secrets in this article refer to the seed phrase(mnemonic) and private keys.<\/p>\n\n\n\n<h3>\ud83e\udd8aKeyring<\/h3>\n\n\n\n<p><strong>Keyring<\/strong> is the core concept of the secret storing and account management system in MetaMask. <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\">KeyringController<\/a> is the implementation of the keyring. Cited from the KeyringController <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/master\/README.md\">README<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>A module for managing groups of Ethereum accounts called \"Keyrings\", defined originally for MetaMask's multiple-account-type feature.\n\nThe KeyringController has three main responsibilities:\n    *Initializing &amp; using (signing with) groups of Ethereum accounts (\"keyrings\").\n    *Keeping track of local nicknames for those individual accounts.\n    *Providing password-encryption persisting &amp; restoring of secret information.<\/code><\/pre>\n\n\n\n<p>Here is the visual reference of the keyring structure: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-07-at-11.20.41-AM-1-863x1024.png\" alt=\"\" class=\"wp-image-1185\" width=\"432\" height=\"512\" srcset=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-07-at-11.20.41-AM-1-863x1024.png 863w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-07-at-11.20.41-AM-1-253x300.png 253w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-07-at-11.20.41-AM-1-768x911.png 768w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2021\/01\/Screen-Shot-2021-01-07-at-11.20.41-AM-1.png 967w\" sizes=\"(max-width: 432px) 100vw, 432px\" \/><\/figure>\n\n\n\n<p>The circular ring represents the seed phrase that is used to generate public key-private key pairs. Each key hangs on the ring is an individual wallet account with its private key drives from the seed phase. The seed phrase and all accounts data get bundled together, encrypted with an encryption key generated from the user password, and stores in the extension.<\/p>\n\n\n\n<p>The KeyringController uses the &#8220;obs-store&#8221; class to store data. &#8220;obs-store&#8221; stands for ObservableStore, which is a synchronous in-memory store for a single value. The code also references the obs-store as a &#8220;<strong>Vault<\/strong>&#8220;. Let&#8217;s take a closer look at how it&#8217;s implemented: Two <code>ObservableStore<\/code> objects are created inside the <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L26\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L26\">KeyringController constructor<\/a>, one named &#8220;<code>this.store<\/code>&#8221; and&nbsp; another one named &#8220;<code>this.memStore<\/code>&#8220;: &nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/AVqrCzrFG56xHcERypXP9YztqJndOTYnQwMbHu3nloTPs_rt1UKsrwm8v2h-PuGyLDM-2dmCtFvF705XwKJqWBjdn2_GUxpL4qK2n-n0ybCcjCv2cgPVJPrRgaXd1c1BXWcQWK74\" alt=\"\"\/><\/figure>\n\n\n\n<p><code>this.store<\/code> stores the <strong>encrypted<\/strong> wallet secret. Data in <code>this.store<\/code> will be put into the chrome extension local store for persistence data storage. Users can access the data by entering the following code in the extension development console.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chrome.storage.local.get('data', result => {\n    var vault = result.data.KeyringController.vault\n    console.log(vault)\n})<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/PmierCh5NN78KGyXBRdto-iMbyMFW1rdxdohlOjMy98-j-gsYDDYmQilOrqxmoTuamilwmIvH1-8Zo4Qt9w_3GBtc54gQ8F0j1Gr6RqT27u0QUs_BNlHWFlNHIsl1oWPP0pj7Luw\" alt=\"\"\/><\/figure>\n\n\n\n<p><code>this.memStore<\/code>, on the other hand, stores&nbsp;the <strong>decrypted<\/strong>&nbsp;wallet secrets. Data in this object stays in memory and will not be put into the browser&#8217;s persistent storage. When you open the MetaMask extension and enter your password, your decrypted account private key will be stored in the <code>this.memStore<\/code> object for any future use.&nbsp;<a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L143\">Reference 1<\/a>, <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L732\">Reference 2<\/a><\/p>\n\n\n\n<h3>\ud83e\udd8aencryptor<\/h3>\n\n\n\n<p>Inside the KeyringController class, the encryption and decryption operation is performed by the <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L37\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L37\">encryptor<\/a> object. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Ex1. Encrypt keyring data:\nreturn this.encryptor.encrypt(this.password, serializedKeyrings)\n\nEx2. Decrypt the encryptedVault\nconst vault = await this.encryptor.decrypt(password, encryptedVault)<\/code><\/pre>\n\n\n\n<p>The encryptor object is assigned in the KeyringController constructor<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM-1024x359.png\" alt=\"\" class=\"wp-image-998\" width=\"580\" height=\"203\" srcset=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM-1024x359.png 1024w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM-300x105.png 300w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM-768x269.png 768w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM-1536x538.png 1536w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-20-at-5.06.30-PM.png 1706w\" sizes=\"(max-width: 580px) 100vw, 580px\" \/><\/figure>\n\n\n\n<p>The extension and the mobile app uses a different encryptor. The extension uses the&nbsp;<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/www.npmjs.com\/package\/browser-passworder\">browser-passworder<\/a>&nbsp;module, its source code is&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/danfinlay\/browser-passworder\" target=\"_blank\">available<\/a>&nbsp;on Github. The mobile app has its own&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/develop\/app\/core\/Encryptor.js\" target=\"_blank\">encryptor<\/a>&nbsp;class. They work pretty much the same, except for the <a href=\"https:\/\/en.wikipedia.org\/wiki\/PBKDF2\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/PBKDF2\">PBKDF2<\/a> iteration and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Advanced_Encryption_Standard\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Advanced_Encryption_Standard\">AES<\/a> mode. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>browser-passworder: \nGenerate enc_key from password: PBKDF2, 10000 iteration\nAES mode: AES-GCM\n\nMobile app encryptor: \nGenerate enc_key from password: PBKDF2, 5000 iteration\nAES mode: AES-CBC<\/code><\/pre>\n\n\n\n<h3>\ud83e\udd8aMobile App<\/h3>\n\n\n\n<p>Similar to extension, the mobile app adopts the Keyring structure to store secrets and manage accounts. For persistent storage, the app stores encrypted data with the <a href=\"https:\/\/github.com\/react-native-async-storage\/async-storage\" data-type=\"URL\" data-id=\"https:\/\/github.com\/react-native-async-storage\/async-storage\">async-storage<\/a> module that define in the <code><a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/store\/index.js#L44\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/store\/index.js#L44\">persistConfig<\/a><\/code>. The only <a href=\"https:\/\/reactnative.dev\/docs\/asyncstorage\" data-type=\"URL\" data-id=\"https:\/\/reactnative.dev\/docs\/asyncstorage\">official documentation<\/a> I can find that describe how &#8220;async-storage&#8221; work says:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>On iOS, AsyncStorage is backed by native code that stores small values in a serialized dictionary and larger values in separate files. \n\nOn Android, AsyncStorage will use either RocksDB or SQLite based on what is available.<\/code><\/pre>\n\n\n\n<p>The mobile wallet provides the &#8220;remember me&#8221; and &#8216;unlock with touch ID\/device passcode&#8221; options. Users don&#8217;t need to enter their password every time they open the app on their mobile devices.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/lh4.googleusercontent.com\/950lj8d2ir46nDbVlq4gDMePqrKF_zmARY5DOmDpLpI35Z6G3P1wpKCGghbFyLgghYCyKSTn1AbOZ4mg-3lAXNBD7VZJviC9rUtlaKYXzyeyjy6sMYhrc3pxvpkz0uoAIAGEO2iu\" alt=\"\" width=\"188\" height=\"334\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/lh3.googleusercontent.com\/X5aJa5OykYtxd8Es7893vZ3BRdjCAyde1hwScLjgJ9uG9UZj5cvCnFkE27jsc1voKsjOU5-nWCgDAv_41AFv-0R-WtX4MV0T2cCnr__ETNR4FLOInji9drqwxY7gG9R5WXssXG7N\" alt=\"\" width=\"188\" height=\"252\"><\/figure><\/div><br><br><br><br><br><br><br><br><br><br><br><br>\n\n\n\n<p>To achieve this, the MetaMask mobile app stores the user password in the device with the <a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L32\">SecureKeychain<\/a> module, which builds upon the &#8220;<a href=\"https:\/\/github.com\/oblador\/react-native-keychain\">react-native-keychain<\/a>&#8220;.&nbsp;The user password is used to generate the key to decrypt the encrypted wallet secret in persistent storage. <\/p>\n\n\n\n<p>Quick note on how &#8220;react-native-keychain&#8221; stores data in mobile devices:<\/p>\n\n\n\n<ul><li>iOS: Store data in <a href=\"https:\/\/developer.apple.com\/documentation\/security\/keychain_services\" data-type=\"URL\" data-id=\"https:\/\/developer.apple.com\/documentation\/security\/keychain_services\">iOS Keychain<\/a><\/li><li>Android: Encrypt data with the <a href=\"https:\/\/developer.android.com\/training\/articles\/keystore\" data-type=\"URL\" data-id=\"https:\/\/developer.android.com\/training\/articles\/keystore\">Android Keystore<\/a>, stored the encrypted data in SharedPreferences <\/li><\/ul>\n\n\n\n<h3>\ud83e\udd8a<a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L32\">SecureKeychain<\/a><\/h3>\n\n\n\n<p>Comment in the code explain what the SecureKeychain does:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n* Class that wraps Keychain from react-native-keychain\n* abstracting metamask specific functionality and settings\n* and also adding an extra layer of encryption before writing into\n* the phone's keychain\n*\/\nclass SecureKeychain {\n...\n}<\/code><\/pre>\n\n\n\n<p>&#8220;abstracting metamask specific functionality and settings&#8221; refers to the &#8220;remember me&#8221; and &#8220;sign in with touch ID\/device passcode&#8221; feature. Check out the <code>resetGenericPassword<\/code>, <code>getGenericPassword<\/code> and <code>setGenericPassword<\/code> function to see how it&#8217;s implemented. <\/p>\n\n\n\n<p>As for &#8220;adding an extra layer of encryption&#8221;, I am curious about what&#8217;s the encryption key used here to perform the encryption? Here is the relevant code path I found:<\/p>\n\n\n\n<ol><li>The <code>code<\/code> in the constructor is used as the encryption key. (<a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L35\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L35\">Source<\/a>)<\/li><li>In the init(salt) function, the SecureKeychain object is created with the argument &#8216;salt&#8217; (<a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L54\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/core\/SecureKeychain.js#L54\">Source<\/a>)<\/li><li>The <code>init<\/code> function is called with the argument <code>props.foxCode<\/code> (<a href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/components\/Views\/Root\/index.js#L34\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-mobile\/blob\/efc39fb6c794fe574fcf33fc2f71b2a069ecc4e7\/app\/components\/Views\/Root\/index.js#L34\">Source<\/a>)<\/li><\/ol>\n\n\n\n<p>What is the <code>foxCode<\/code>? I searched in the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/MetaMask\/metamask-mobile\" target=\"_blank\">mobile wallet repository<\/a>&nbsp;and all public repositories under the&nbsp;<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/github.com\/MetaMask\">MetaMask organization<\/a>, but no result. Hmm\ud83e\udd14, how about the app binary? &nbsp;<\/p>\n\n\n\n<p>I download the <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=io.metamask&amp;hl=en_US&amp;gl=US\" data-type=\"URL\" data-id=\"https:\/\/play.google.com\/store\/apps\/details?id=io.metamask&amp;hl=en_US&amp;gl=US\">Metamask<\/a> APK with this <a href=\"https:\/\/apps.evozi.com\/apk-downloader\/\" data-type=\"URL\" data-id=\"https:\/\/apps.evozi.com\/apk-downloader\/\">tool<\/a>, de-package with <a href=\"https:\/\/github.com\/skylot\/jadx\" data-type=\"URL\" data-id=\"https:\/\/github.com\/skylot\/jadx\">jadx<\/a>, search for the string &#8220;foxCode&#8221; and found this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"257\" src=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-2.01.38-AM-1-1024x257.png\" alt=\"\" class=\"wp-image-848\" srcset=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-2.01.38-AM-1-1024x257.png 1024w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-2.01.38-AM-1-300x75.png 300w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-2.01.38-AM-1-768x193.png 768w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-2.01.38-AM-1.png 1500w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Wait, so the <strong>foxCode<\/strong> equal to the string &#8220;encrypt&#8221;? What&#8217;s the point of encrypting something with a hardcoded string? \ud83e\udd14<\/p>\n\n\n\n<p>I send an email to the Metamask security team and ask for why does the user password encrypted with the hardcoded string(the&nbsp;foxCode) &#8220;encrypt&#8221;, the team responded:&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"424\" src=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-1024x424.png\" alt=\"\" class=\"wp-image-840\" srcset=\"https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-1024x424.png 1024w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-300x124.png 300w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-768x318.png 768w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-1536x636.png 1536w, https:\/\/www.wispwisp.com\/wp-content\/uploads\/2020\/12\/Screen-Shot-2020-12-18-at-1.54.12-AM-2048x848.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I pretty much agree with him. But I still wonder why such code gets put in the codebase in the first place. <\/p>\n\n\n\n<h3>\ud83e\udd8aThe end<\/h3>\n\n\n\n<p>This is the end of the article. I hope it explains the basics of how MetaMask wallet stores your wallet secret. If you want to know more details, you can read its source code in their GitHub repo https:\/\/github.com\/MetaMask.<\/p>\n\n\n\n<p>==========================\ud83e\udd8aAppendix\ud83e\udd8a==========================<\/p>\n\n\n\n<p>A very rough code path for the new wallet creation:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">1. <a href=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/pages\/first-time-flow\/first-time-flow.component.js#L70\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/pages\/first-time-flow\/first-time-flow.component.js#L70\">metamask-extension\/ui\/app\/pages\/first-time-flow\/first-time-flow.component.js<\/a>  &lt;-- Click Me\nconst seedPhrase = await createNewAccount(password)\n\n2. <a href=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/pages\/first-time-flow\/first-time-flow.container.js#L37\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/pages\/first-time-flow\/first-time-flow.container.js#L37\">metamask-extension\/ui\/app\/pages\/first-time-flow\/first-time-flow.container.js<\/a>\ncreateNewAccount: (password) =&gt;\ndispatch(createNewVaultAndGetSeedPhrase(password))\n\n3. <a href=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/store\/actions.js#L117\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/ui\/app\/store\/actions.js#L117\">metamask-extension\/ui\/app\/store\/actions.js<\/a>\nexport function createNewVaultAndGetSeedPhrase(password){\n    ....\n    await createNewVault(password)\n    const seedWords = await verifySeedPhrase()\n    ....\n}\n\n4. <a href=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/app\/scripts\/metamask-controller.js#L865\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/metamask-extension\/blob\/889ca62723b53516d28c9307f766ca4e065cc126\/app\/scripts\/metamask-controller.js#L865\">metamask-extension\/app\/scripts\/metamask-controller.js<\/a>\nasync createNewVaultAndKeychain(password){\n    vault = await this.keyringController.createNewVaultAndKeychain(password)\n}\n\n5. <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L70\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L70\">KeyringController\/blob\/master\/index.js<\/a>\ncreateNewVaultAndKeychain (password) {\n    return this.persistAllKeyrings(password)\n        .then(this.createFirstKeyTree.bind(this))\n        .then(this.persistAllKeyrings.bind(this, password))\n        .then(this.setUnlocked.bind(this))\n        .then(this.fullUpdate.bind(this))\n}\n\n6. <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L492\">MetaMask\/KeyringController\/blob\/master\/index.js<\/a> createFirstKeyTree () {\n    ... \n    return this.addNewKeyring('HD Key Tree', { numberOfAccounts: 1 })\n    ... \n} \n\n7. <a href=\"https:\/\/github.com\/MetaMask\/KeyringController\/blob\/1a0dbbaf45e54e7b80200d4a9c6b21ce74b61b2f\/index.js#L103\">MetaMask\/KeyringController\/blob\/master\/index.js<\/a> addNewKeyring (type, opts) { \n    ... \n    const Keyring = this.getKeyringClassForType(type)\n    const keyring = new Keyring(opts)\n    ... \n}\n\n8. <a href=\"https:\/\/github.com\/MetaMask\/eth-hd-keyring\/blob\/44d2b1effc0eec0eaf811763eb74ec3118b6903e\/index.js#L45\" data-type=\"URL\" data-id=\"https:\/\/github.com\/MetaMask\/eth-hd-keyring\/blob\/44d2b1effc0eec0eaf811763eb74ec3118b6903e\/index.js#L45\">MetaMask\/eth-hd-keyring\/blob\/master\/index.js<\/a>\naddAccounts (numberOfAccounts = 1) {\n    ...\n    this._initFromMnemonic(bip39.generateMnemonic())\n    ...\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>As a security engineer\/pentester in the blockchain space, I have tested many crypto wallet applications during research and client engagements. After seeing different ways of handing secrets in different wallets, I was curious about how MetaMask, one of the most famous crypto wallets in the space, does it. Well, if you ask me why I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1170,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/posts\/770"}],"collection":[{"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/comments?post=770"}],"version-history":[{"count":402,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/posts\/770\/revisions"}],"predecessor-version":[{"id":1200,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/posts\/770\/revisions\/1200"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/media\/1170"}],"wp:attachment":[{"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/media?parent=770"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/categories?post=770"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wispwisp.com\/index.php\/wp-json\/wp\/v2\/tags?post=770"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}