Created
June 24, 2024 09:54
-
-
Save jeasonstudio/617becf209bcbb5afaab34decae3e4be to your computer and use it in GitHub Desktop.
Convert MetaMask snap(arsnap) into JWK file, and you can import to ArConnect Wallet
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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Arweave Keyfile Converter</title> | |
</head> | |
<body> | |
<main> | |
<input | |
type="text" | |
id="mnemonic" | |
style="width: 800px" | |
placeholder="Please input your metamask mnemonic" | |
/> | |
<button onclick="downloadfile()">download arweave JWK</button> | |
</main> | |
<script type="module"> | |
import bip39 from 'https://esm.sh/bip39?bundle-deps'; | |
import FileSaver from 'https://esm.sh/file-saver?bundle-deps'; | |
import { SLIP10Node } from 'https://esm.sh/@metamask/key-tree?bundle-deps'; | |
import init, { | |
keygen, | |
} from 'https://esm.sh/@pianity/arsnap-keygen?bundle-deps'; | |
function hexToUint8Array(hex) { | |
const chunks = []; | |
for (let i = 0; i < hex.length; i += 2) { | |
chunks.push(hex.slice(i, i + 2)); | |
} | |
return new Uint8Array(chunks.map((chunk) => parseInt(chunk, 16))); | |
} | |
function base64ToUint8Array(base64String) { | |
const binaryString = window.atob(base64String); | |
const len = binaryString.length; | |
const bytes = new Uint8Array(len); | |
for (let i = 0; i < len; i++) { | |
bytes[i] = binaryString.charCodeAt(i); | |
} | |
return bytes; | |
} | |
/** | |
* Convert the pem string to a binary representation | |
*/ | |
function pemToBin(pem) { | |
const encoded = pem | |
.split('\n') | |
.reduce( | |
(lines, line) => (line.indexOf('-----') < 0 ? lines + line : lines), | |
'' | |
); | |
return base64ToUint8Array(encoded); | |
} | |
/** | |
* Convert the pem key to the official arweave key format | |
*/ | |
async function pemToJwk(pem) { | |
const cryptoKey = await window.crypto.subtle.importKey( | |
'pkcs8', | |
pemToBin(pem), | |
{ | |
name: 'RSA-PSS', | |
hash: { name: 'SHA-256' }, | |
}, | |
true, | |
['sign'] | |
); | |
const jwk = await crypto.subtle.exportKey('jwk', cryptoKey); | |
return { | |
kty: jwk.kty, | |
n: jwk.n, | |
e: jwk.e, | |
d: jwk.d, | |
p: jwk.p, | |
q: jwk.q, | |
dp: jwk.dp, | |
dq: jwk.dq, | |
qi: jwk.qi, | |
}; | |
} | |
async function main(mnemonic) { | |
await init(); | |
const ed25519Node = await SLIP10Node.fromDerivationPath({ | |
curve: 'ed25519', | |
derivationPath: [ | |
`bip39:${mnemonic}`, | |
`slip10:44'`, | |
`slip10:472'`, | |
`slip10:0'`, | |
], | |
}); | |
const privateKey = ed25519Node.privateKey.slice(2); | |
const secret = hexToUint8Array(privateKey); | |
const pem = await keygen(secret); | |
const jwk = await pemToJwk(pem); | |
console.log(jwk); | |
return jwk; | |
} | |
window.downloadfile = async () => { | |
try { | |
const mnemonic = document.getElementById('mnemonic').value; | |
const result = await main(mnemonic); | |
const blob = new Blob([JSON.stringify(result, null, 2)], { | |
type: 'text/plain;charset=utf-8', | |
}); | |
await FileSaver.saveAs(blob, 'keyfile.json'); | |
} catch (error) { | |
alert('Error:' + JSON.stringify(error)); | |
} | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment