-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
var ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; | ||
var ALPHABET_MAP = {}; | ||
for (var z = 0; z < ALPHABET.length; z++) { | ||
var x = ALPHABET.charAt(z); | ||
ALPHABET_MAP[x] = z; | ||
} | ||
function polymodStep(pre) { | ||
var b = pre >> 25; | ||
return (((pre & 0x1ffffff) << 5) ^ | ||
(-((b >> 0) & 1) & 0x3b6a57b2) ^ | ||
(-((b >> 1) & 1) & 0x26508e6d) ^ | ||
(-((b >> 2) & 1) & 0x1ea119fa) ^ | ||
(-((b >> 3) & 1) & 0x3d4233dd) ^ | ||
(-((b >> 4) & 1) & 0x2a1462b3)); | ||
} | ||
function prefixChk(prefix) { | ||
var chk = 1; | ||
for (var i = 0; i < prefix.length; ++i) { | ||
var c = prefix.charCodeAt(i); | ||
if (c < 33 || c > 126) | ||
return 'Invalid prefix (' + prefix + ')'; | ||
chk = polymodStep(chk) ^ (c >> 5); | ||
} | ||
chk = polymodStep(chk); | ||
for (var i = 0; i < prefix.length; ++i) { | ||
var v = prefix.charCodeAt(i); | ||
chk = polymodStep(chk) ^ (v & 0x1f); | ||
} | ||
return chk; | ||
} | ||
function convertbits(data, inBits, outBits, pad) { | ||
var value = 0; | ||
var bits = 0; | ||
var maxV = (1 << outBits) - 1; | ||
var result = []; | ||
for (var i = 0; i < data.length; ++i) { | ||
value = (value << inBits) | data[i]; | ||
bits += inBits; | ||
while (bits >= outBits) { | ||
bits -= outBits; | ||
result.push((value >> bits) & maxV); | ||
} | ||
} | ||
if (pad) { | ||
if (bits > 0) { | ||
result.push((value << (outBits - bits)) & maxV); | ||
} | ||
} | ||
else { | ||
if (bits >= inBits) | ||
return 'Excess padding'; | ||
if ((value << (outBits - bits)) & maxV) | ||
return 'Non-zero padding'; | ||
} | ||
return result; | ||
} | ||
function toWords(bytes) { | ||
return convertbits(bytes, 8, 5, true); | ||
} | ||
function fromWordsUnsafe(words) { | ||
var res = convertbits(words, 5, 8, false); | ||
if (Array.isArray(res)) | ||
return res; | ||
} | ||
function fromWords(words) { | ||
var res = convertbits(words, 5, 8, false); | ||
if (Array.isArray(res)) | ||
return res; | ||
throw new Error(res); | ||
} | ||
function getLibraryFromEncoding(encoding) { | ||
var ENCODING_CONST; | ||
if (encoding === 'bech32') { | ||
ENCODING_CONST = 1; | ||
} | ||
else { | ||
ENCODING_CONST = 0x2bc830a3; | ||
} | ||
function encode(prefix, words, LIMIT) { | ||
LIMIT = LIMIT || 90; | ||
if (prefix.length + 7 + words.length > LIMIT) | ||
throw new TypeError('Exceeds length limit'); | ||
prefix = prefix.toLowerCase(); | ||
// determine chk mod | ||
var chk = prefixChk(prefix); | ||
if (typeof chk === 'string') | ||
throw new Error(chk); | ||
var result = prefix + '1'; | ||
for (var i = 0; i < words.length; ++i) { | ||
var x = words[i]; | ||
if (x >> 5 !== 0) | ||
throw new Error('Non 5-bit word'); | ||
chk = polymodStep(chk) ^ x; | ||
result += ALPHABET.charAt(x); | ||
} | ||
for (var i = 0; i < 6; ++i) { | ||
chk = polymodStep(chk); | ||
} | ||
chk ^= ENCODING_CONST; | ||
for (var i = 0; i < 6; ++i) { | ||
var v = (chk >> ((5 - i) * 5)) & 0x1f; | ||
result += ALPHABET.charAt(v); | ||
} | ||
return result; | ||
} | ||
function __decode(str, LIMIT) { | ||
LIMIT = LIMIT || 90; | ||
if (str.length < 8) | ||
return str + ' too short'; | ||
if (str.length > LIMIT) | ||
return 'Exceeds length limit'; | ||
// don't allow mixed case | ||
var lowered = str.toLowerCase(); | ||
var uppered = str.toUpperCase(); | ||
if (str !== lowered && str !== uppered) | ||
return 'Mixed-case string ' + str; | ||
str = lowered; | ||
var split = str.lastIndexOf('1'); | ||
if (split === -1) | ||
return 'No separator character for ' + str; | ||
if (split === 0) | ||
return 'Missing prefix for ' + str; | ||
var prefix = str.slice(0, split); | ||
var wordChars = str.slice(split + 1); | ||
if (wordChars.length < 6) | ||
return 'Data too short'; | ||
var chk = prefixChk(prefix); | ||
if (typeof chk === 'string') | ||
return chk; | ||
var words = []; | ||
for (var i = 0; i < wordChars.length; ++i) { | ||
var c = wordChars.charAt(i); | ||
var v = ALPHABET_MAP[c]; | ||
if (v === undefined) | ||
return 'Unknown character ' + c; | ||
chk = polymodStep(chk) ^ v; | ||
// not in the checksum? | ||
if (i + 6 >= wordChars.length) | ||
continue; | ||
words.push(v); | ||
} | ||
if (chk !== ENCODING_CONST) | ||
return 'Invalid checksum for ' + str; | ||
return { prefix: prefix, words: words }; | ||
} | ||
function decodeUnsafe(str, LIMIT) { | ||
var res = __decode(str, LIMIT); | ||
if (typeof res === 'object') | ||
return res; | ||
} | ||
function decode(str, LIMIT) { | ||
var res = __decode(str, LIMIT); | ||
if (typeof res === 'object') | ||
return res; | ||
throw new Error(res); | ||
} | ||
return { | ||
decodeUnsafe: decodeUnsafe, | ||
decode: decode, | ||
encode: encode, | ||
toWords: toWords, | ||
fromWordsUnsafe: fromWordsUnsafe, | ||
fromWords: fromWords | ||
}; | ||
} | ||
|
||
const bech32 = getLibraryFromEncoding('bech32'); | ||
const bech32m = getLibraryFromEncoding('bech32m'); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<!DOCTYPE HTML> | ||
<html> | ||
<head> | ||
<title>nPUB to HEX | nstr.cloud</title> | ||
<meta charset="utf-8"/> | ||
<meta author="NSTR.cloud"/> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/> | ||
<link rel="stylesheet" href="assets/css/main.css"/> | ||
<script src="assets/js/particles.min.js"></script> | ||
</head> | ||
<script>particlesJS.load('particles-js', 'assets/js/particles.json', function() {});</script> | ||
<body class="is-preload"> | ||
<div id="particles-js"></div> | ||
<div id="wrapper"> | ||
<section id="main"> | ||
<div class="container"> | ||
<h1><a href="https://nstr.cloud/">KEY CONVERTER</a></h1> | ||
<label for="bech32">nPUB key</label> | ||
<input type="text" class="u-full-width" placeholder="nPUB/nSEC..." id="pub-key"> | ||
<br> | ||
<label for="bech32">HEX key</label> | ||
<input type="text" class="u-full-width" placeholder="" id="hex-key" readonly> | ||
</div> | ||
</section> | ||
</div> | ||
<script> | ||
if('addEventListener' in window){ | ||
window.addEventListener('load', function() { document.body.className = document.body.className.replace(/\bis-preload\b/, ''); }); | ||
document.body.className += (navigator.userAgent.match(/(MSIE|rv:11\.0)/) ? ' is-ie' : ''); | ||
} | ||
</script> | ||
<script src="bech32.js" ></script> | ||
<script src="key.js" ></script> | ||
</body> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
function hex_char(val) | ||
{ | ||
if (val < 10) | ||
return String.fromCharCode(48 + val) | ||
if (val < 16) | ||
return String.fromCharCode(97 + val - 10) | ||
} | ||
|
||
function hex_encode(buf) | ||
{ | ||
str = "" | ||
for (let i = 0; i < buf.length; i++) { | ||
const c = buf[i] | ||
str += hex_char(c >> 4) | ||
str += hex_char(c & 0xF) | ||
} | ||
return str | ||
} | ||
|
||
function go() { | ||
const el = document.querySelector("#pub-key") | ||
const hex_el = document.querySelector("#hex-key") | ||
const note_link_el = document.querySelector("#note-link") | ||
const profile_link_el = document.querySelector("#profile-link") | ||
|
||
el.addEventListener("input", () => { | ||
const decoded = bech32.decode(el.value) | ||
const bytes = fromWords(decoded.words) | ||
hex_el.value = hex_encode(bytes) | ||
update_note_link(hex_el.value) | ||
}); | ||
|
||
hex_el.addEventListener("input", () => { | ||
update_note_link(hex_el.value) | ||
}) | ||
|
||
function update_note_link(id) { | ||
note_link_el.href = `nostr:e:${id}` | ||
profile_link_el.href = `nostr:p:${id}` | ||
} | ||
} | ||
|
||
go() |