├── Launch Source Code (Archived) ├── index.html ├── sw.js └── ww.js ├── License ├── README.md ├── authed_contract.sol ├── better_notes_contract.sol ├── mod_contract.sol ├── screenshots ├── alert.png ├── cost.png ├── group61.png ├── hero.png ├── homescreen.jpg ├── note.webp ├── note2.png └── updates.png └── sec_keys.sol /Launch Source Code (Archived)/sw.js: -------------------------------------------------------------------------------- 1 | let sw_version = "02"; 2 | let cache_version_number = "01"; 3 | (function() { 4 | var cache_version = 'bitnote_' + cache_version_number; 5 | var pre_cache_files = ['/', 'sw.js', 'pages/js/zxcvbn.js', 'pages/js/ww.js', 'manifest.json', 'pages/js/new_wl.js', 'pages/fonts/bitnote_box_font.woff2', 'pages/fonts/inter_variable.ttf', ]; 6 | var pre_load_files = ['/', 'sw.js', 'pages/js/ww.js', 'manifest.json', 'pages/js/new_wl.js', 'pages/fonts/bitnote_box_font.woff2', 'pages/fonts/inter_variable.ttf', ]; 7 | var non_static_files = ['/', 'sw.js', 'pages/js/ww.js', 'manifest.json', ]; 8 | function checkVersion(cb) { 9 | fetch("/pages/live_version.txt?_=" + Date.now()).then(function(response) { 10 | const reader = response.body.getReader(); 11 | reader.read().then(function processText({done, value}) { 12 | var version = new TextDecoder().decode(value).split('\n')[0]; 13 | cb(version); 14 | }); 15 | }); 16 | } 17 | self.addEventListener('install', function(event) { 18 | event.waitUntil(caches.open(cache_version).then(function(cache) { 19 | cache.keys().then(function(keys) { 20 | if (keys.length === 0) 21 | return cache.addAll(pre_cache_files); 22 | }); 23 | })); 24 | console.log("skipping install wait"); 25 | self.skipWaiting(); 26 | }); 27 | self.addEventListener('activate', function(event) { 28 | console.log("waiting on activate claim"); 29 | event.waitUntil(self.clients.claim()); 30 | }); 31 | function updateVersion(full_clear=false, cb) { 32 | (function clearCache() { 33 | caches.keys().then(function(keys) { 34 | if (full_clear) { 35 | Promise.all(keys.map(function(cacheName) { 36 | return caches.delete(cacheName); 37 | })); 38 | } else { 39 | return Promise.all(keys.map(function(key) { 40 | return caches.open(key).then(function(cache) { 41 | return Promise.all(non_static_files.map(function(filename) { 42 | return cache.delete(filename); 43 | })); 44 | }); 45 | })); 46 | } 47 | }).then(updateCache); 48 | } 49 | )(); 50 | function updateCache() { 51 | caches.open(cache_version).then(function(cache) { 52 | if (full_clear) 53 | hardRefresh(pre_cache_files, cache); 54 | else 55 | hardRefresh(non_static_files, cache); 56 | }); 57 | function hardRefresh(array_list, cache) { 58 | var date = Date.now(); 59 | var file_list = array_list.map(function(filename) { 60 | return filename + "?_" + date 61 | }); 62 | var first = file_list.shift(); 63 | fetch(first).then(function(response) { 64 | cacheResponse(response); 65 | var promises = file_list.map(function(file) { 66 | return fetch(file).then(cacheResponse); 67 | }); 68 | Promise.all(promises).then(cb); 69 | }); 70 | function cacheResponse(response) { 71 | if (response.status === 200) 72 | return cache.put(response.url.split('?')[0], response); 73 | } 74 | } 75 | } 76 | } 77 | self.addEventListener('fetch', standardFetch); 78 | function standardFetch(e) { 79 | if (e.request.method === 'GET') { 80 | e.respondWith(caches.open(cache_version).then(function(cache) { 81 | var match_url = stripUsername(e.request); 82 | return cache.match(match_url, { 83 | ignoreSearch: true 84 | }).then(function(response) { 85 | return response || fetch(e.request).then(function(response) { 86 | if (response.status === 200) { 87 | if (e.request.url.includes(self.location.hostname)) { 88 | var temp_url = e.request.url.replace(self.location.hostname, ""); 89 | if (pre_cache_files.includes(temp_url)) 90 | cache.put(e.request, response.clone()); 91 | } 92 | } 93 | return response; 94 | }); 95 | }); 96 | })); 97 | } 98 | } 99 | function stripUsername(request) { 100 | var url = new URL(request.url); 101 | if (url.pathname != "/" && url.origin === self.location.origin) { 102 | var username = url.pathname.match(/\/.*?\//); 103 | if (checkForProperty(username)) { 104 | username = username[0].replaceAll("/", ""); 105 | if (username != "pages") 106 | return url.origin; 107 | } 108 | } 109 | return request; 110 | } 111 | self.addEventListener('message', messageReceiver); 112 | function messageReceiver(msg) { 113 | if (msg.ports) { 114 | switch (msg.data.type) { 115 | case "init": 116 | checkVersion(function(ret) { 117 | console.log(ret); 118 | msg.ports[0].postMessage({ 119 | type: "version_check", 120 | sw_version: sw_version, 121 | live_version: ret 122 | }); 123 | }); 124 | break; 125 | case "update_version": 126 | updateVersion(false, function(ret) { 127 | msg.ports[0].postMessage({ 128 | type: "update_result", 129 | response: ret 130 | }); 131 | }); 132 | break; 133 | case "clear_cache": 134 | updateVersion(true, function(ret) { 135 | msg.ports[0].postMessage({ 136 | type: "clear_cache", 137 | response: ret 138 | }); 139 | }); 140 | break; 141 | } 142 | } 143 | } 144 | function checkForProperty(prop) { 145 | return (prop === "" || prop === null || prop === undefined) ? false : true; 146 | } 147 | } 148 | )(); 149 | -------------------------------------------------------------------------------- /Launch Source Code (Archived)/ww.js: -------------------------------------------------------------------------------- 1 | let ww_version = "01"; 2 | self.addEventListener("message", handleMessage); 3 | let eh = new ww_encryption_handler(); 4 | let active_mp_buff = null; 5 | let active_pk_buff = null; 6 | let active_ecdh_priv_buff = null; 7 | let secp_h; 8 | let salt_byte_len = 12; 9 | let salt_hex_len = 24; 10 | function handleMessage(msg_event) { 11 | var msg_type = msg_event.data.msg_type; 12 | switch (msg_type) { 13 | case "get_version": 14 | self.postMessage(ww_version); 15 | break; 16 | case "ecdh_enc": 17 | var ecdh_pk_buff = (checkForProperty(msg_event.data.ecdh_pk_buff)) ? msg_event.data.ecdh_pk_buff : active_ecdh_priv_buff; 18 | newEcdhEncrypt(msg_event.data.msg_buff, msg_event.data.ecdh_pub, msg_event.data.aad, ecdh_pk_buff, function(encrypted_buff, salt_buff) { 19 | self.postMessage({ 20 | encrypted_buff: encrypted_buff, 21 | salt_buff: salt_buff 22 | }, [encrypted_buff, salt_buff]); 23 | }); 24 | break; 25 | case "ecdh_de": 26 | var ecdh_pk_buff = (checkForProperty(msg_event.data.ecdh_pk_buff)) ? msg_event.data.ecdh_pk_buff : active_ecdh_priv_buff; 27 | newEcdhDecrypt(msg_event.data.msg_buff, msg_event.data.ecdh_pub, msg_event.data.aad, ecdh_pk_buff, function(decrypted_buff) { 28 | if (decrypted_buff != null) 29 | self.postMessage({ 30 | decrypted_buff: decrypted_buff 31 | }, [decrypted_buff]); 32 | else 33 | self.postMessage(null); 34 | }); 35 | break; 36 | case "bio_enc": 37 | eh.newMsgDefaultEncrypt(msg_event.data.msg_buff, msg_event.data.key_buff, function(salt_buff, encrypted_buff) { 38 | self.postMessage({ 39 | salt_buff: salt_buff, 40 | encrypted_buff: encrypted_buff 41 | }, [salt_buff, encrypted_buff]); 42 | }); 43 | break; 44 | case "bio_de": 45 | iterations = 1000000; 46 | decryptPrep(msg_event.data.cipher_buff, msg_event.data.key_buff, msg_event.data.salt_buff, iterations, decryptPost); 47 | break; 48 | case "de": 49 | var mp_buff = (checkForProperty(msg_event.data.mp_buff)) ? msg_event.data.mp_buff : active_mp_buff; 50 | iterations = 1000000; 51 | decryptPrep(msg_event.data.cipher_buff, mp_buff, msg_event.data.salt_buff, iterations, decryptPost); 52 | break; 53 | case "set_mp": 54 | active_mp_buff = msg_event.data.key_buff; 55 | self.postMessage(true); 56 | break; 57 | case "sign_stuff": 58 | if (active_pk_buff != null) 59 | signStuff(msg_event.data.msg_buff); 60 | else 61 | self.postMessage(null); 62 | break; 63 | case "gen_ac": 64 | generateNewAccount(); 65 | break; 66 | case "unlock_ac": 67 | iterations = 1000000; 68 | var decrypt_obj_array = [{ 69 | data_buff: msg_event.data.cipher_buff, 70 | mp_buff: active_mp_buff, 71 | salt_buff: msg_event.data.salt_buff 72 | }, { 73 | data_buff: msg_event.data.ecdh_buff, 74 | mp_buff: active_mp_buff, 75 | salt_buff: msg_event.data.ecdh_salt_buff 76 | }, ]; 77 | multiDecrypt(decrypt_obj_array, iterations, function(decrypted) { 78 | if (decrypted.length == 2 && (decrypted[0] != null && decrypted[1] != null)) { 79 | active_pk_buff = decrypted[0]; 80 | active_ecdh_priv_buff = decrypted[1]; 81 | self.postMessage(true); 82 | } else 83 | self.postMessage(false); 84 | }); 85 | break; 86 | case "remove_keys": 87 | active_mp_buff = null; 88 | active_pk_buff = null; 89 | active_ecdh_priv_buff = null; 90 | self.postMessage(true); 91 | break; 92 | case "check_mp": 93 | self.postMessage((active_mp_buff == null) ? false : true); 94 | break; 95 | case "check_pk": 96 | self.postMessage((active_pk_buff == null) ? false : true); 97 | break; 98 | case "check_both": 99 | self.postMessage((active_pk_buff != null && active_mp_buff != null) ? true : false); 100 | break; 101 | case "new_key_pair": 102 | var new_keys = getNewKeyPairBuffs(); 103 | self.postMessage({ 104 | pk_buff: new_keys.pk_buff, 105 | pub_buff: new_keys.pub_buff 106 | }, [new_keys.pk_buff, new_keys.pub_buff]); 107 | break; 108 | case "encrypt_mp": 109 | eh.hkdfEncrypt(active_mp_buff.slice(), msg_event.data.key_buff, function(salt_buff, encrypted_buff) { 110 | self.postMessage({ 111 | salt_buff: salt_buff, 112 | encrypted_buff: encrypted_buff 113 | }, [salt_buff, encrypted_buff]); 114 | }); 115 | break; 116 | case "decrypt_mp": 117 | eh.hkdfDecrypt(msg_event.data.msg_buff, msg_event.data.key_buff, decryptPost); 118 | break; 119 | } 120 | function signStuff(msg_buff) { 121 | msg_buff = new Uint8Array(msg_buff); 122 | var temp_pk = new Uint8Array(active_pk_buff); 123 | const pub = secp_h.getPublicKey(temp_pk); 124 | var signature = secp_h.sign(msg_buff, temp_pk, { 125 | lowS: true, 126 | extraEntropy: true 127 | }); 128 | console.log(secp_h.verify(signature, msg_buff, pub)); 129 | var r_buff = bigToPaddedHex(signature.r); 130 | var s_buff = bigToPaddedHex(signature.s); 131 | r_buff = hexToArrayBuffer(r_buff, Uint8Array).buffer; 132 | s_buff = hexToArrayBuffer(s_buff, Uint8Array).buffer; 133 | self.postMessage({ 134 | r: r_buff, 135 | s: s_buff, 136 | recovery: signature.recovery 137 | }, [r_buff, s_buff]); 138 | } 139 | function newEcdhEncrypt(msg_buff, ecdh_pub, aad="", ecdh_pk_buff, callback) { 140 | eh.importEcdhKey(ecdh_pk_buff, "privateKey", "deriveKey", "pkcs8", function(imported_priv) { 141 | eh.importEcdhKey(ecdh_pub, "publicKey", null, "raw", function(imported_public) { 142 | eh.deriveEcdhKey(imported_priv, imported_public, function(derived_key) { 143 | var iv = self.crypto.getRandomValues(new Uint8Array(salt_byte_len)); 144 | eh.encrypt(derived_key, msg_buff, iv, function(encrypted_buff) { 145 | callback(encrypted_buff, iv.buffer); 146 | }, aad); 147 | }); 148 | }) 149 | }); 150 | } 151 | function newEcdhDecrypt(msg_buff, ecdh_pub, aad="", ecdh_pk_buff, callback) { 152 | eh.importEcdhKey(ecdh_pk_buff, "privateKey", "deriveKey", "pkcs8", function(imported_priv) { 153 | eh.importEcdhKey(ecdh_pub, "publicKey", null, "raw", function(imported_public) { 154 | eh.deriveEcdhKey(imported_priv, imported_public, function(derived_key) { 155 | var iv = msg_buff.slice(0, salt_byte_len); 156 | msg_buff = msg_buff.slice(salt_byte_len); 157 | eh.noDecodeDecrypt(derived_key, msg_buff, iv, function(decrypted_buff) { 158 | callback(decrypted_buff); 159 | }, aad); 160 | }); 161 | }) 162 | }); 163 | } 164 | function getNewKeyPairBuffs() { 165 | var pk_buff = secp_h.utils.randomPrivateKey(); 166 | var pub_buff = secp_h.getPublicKey(pk_buff, false).buffer; 167 | pk_buff = pk_buff.buffer; 168 | return { 169 | pk_buff, 170 | pub_buff 171 | }; 172 | } 173 | function generateNewAccount() { 174 | var new_keys = getNewKeyPairBuffs(); 175 | var pk_buff = new_keys.pk_buff; 176 | var pub_buff = new_keys.pub_buff; 177 | eh.generateECDHKeys(function(ecdh_keys) { 178 | active_pk_buff = pk_buff; 179 | exportEcdhKeys(ecdh_keys, function(exported_priv, exported_pub) { 180 | active_ecdh_priv_buff = exported_priv; 181 | var enc_obj_array = [{ 182 | data: active_pk_buff, 183 | mp_buff: active_mp_buff 184 | }, { 185 | data: exported_priv, 186 | mp_buff: active_mp_buff 187 | }, ]; 188 | multiEncrypt(enc_obj_array, function(encrypted_array) { 189 | var qq = 22; 190 | self.postMessage({ 191 | pub_buff: pub_buff, 192 | salt_buff: encrypted_array[0].salt_buff, 193 | encrypted_buff: encrypted_array[0].encrypted_buff, 194 | ecdh_priv_buff: encrypted_array[1].encrypted_buff, 195 | ecdh_salt_buff: encrypted_array[1].salt_buff, 196 | ecdh_pub_buff: exported_pub, 197 | }, [pub_buff, encrypted_array[0].salt_buff, encrypted_array[0].encrypted_buff, encrypted_array[1].encrypted_buff, encrypted_array[1].salt_buff, exported_pub]); 198 | }); 199 | }); 200 | }); 201 | } 202 | function exportEcdhKeys(keys, callback) { 203 | eh.exportKey(keys.privateKey, "pkcs8", function(exported_priv) { 204 | eh.exportKey(keys.publicKey, "raw", function(exported_public) { 205 | callback(exported_priv, exported_public); 206 | }); 207 | }); 208 | } 209 | function multiEncrypt(enc_obj_array, callback) { 210 | let end_point = enc_obj_array.length; 211 | let start_point = 0; 212 | let encrypted_array = []; 213 | (function encrypt_next(pointer) { 214 | if (pointer < end_point) { 215 | eh.newMsgDefaultEncrypt(enc_obj_array[pointer].data, enc_obj_array[pointer].mp_buff, function(salt_buff, encrypted_buff) { 216 | encrypted_array.push({ 217 | salt_buff: salt_buff, 218 | encrypted_buff: encrypted_buff 219 | }); 220 | encrypt_next(++pointer); 221 | }); 222 | } else 223 | callback(encrypted_array); 224 | } 225 | )(start_point); 226 | } 227 | function multiDecrypt(decrypt_obj_array, iterations, callback) { 228 | let end_point = decrypt_obj_array.length; 229 | let start_point = 0; 230 | let decrypted_array = []; 231 | (function decrypt_next(pointer) { 232 | if (pointer < end_point) { 233 | eh.defaultDeriveKey(decrypt_obj_array[pointer].mp_buff, iterations, decrypt_obj_array[pointer].salt_buff, function(key) { 234 | eh.noDecodeDecrypt(key, decrypt_obj_array[pointer].data_buff, decrypt_obj_array[pointer].salt_buff, function(decrpyted_stuff) { 235 | decrypted_array.push(decrpyted_stuff); 236 | decrypt_next(++pointer); 237 | }); 238 | }); 239 | } else 240 | callback(decrypted_array); 241 | } 242 | )(start_point); 243 | } 244 | function decryptPrep(cipher_buff, phrase_buff, salt_buff, iterations, cb) { 245 | eh.defaultDeriveKey(phrase_buff, iterations, salt_buff, function(key) { 246 | eh.noDecodeDecrypt(key, cipher_buff, salt_buff, cb); 247 | }); 248 | } 249 | function decryptPost(decrypted) { 250 | if (decrypted != null) 251 | self.postMessage(decrypted, [decrypted]); 252 | else 253 | self.postMessage(null); 254 | } 255 | function checkForProperty(prop) { 256 | return (prop === "" || prop === null || prop === undefined) ? false : true; 257 | } 258 | } 259 | function hexToArrayBuffer(hex_str, buffer_type=null) { 260 | const regex = new RegExp(/0x/i); 261 | if (regex.test(hex_str.substring(0, 2))) 262 | hex_str = hexStringToHexNumber(hex_str); 263 | var ret = []; 264 | for (var i = 0; i < hex_str.length / 2; i++) { 265 | var x = i * 2; 266 | const n = parseInt(hex_str.substr(x, 2), 16); 267 | ret.push(n); 268 | } 269 | if (buffer_type) 270 | return new buffer_type(ret); 271 | else 272 | return ret; 273 | } 274 | function bigToPaddedHex(bigi) { 275 | var hex = bigi.toString(16); 276 | return hex.padStart(32 * 2, '0'); 277 | } 278 | function ww_encryption_handler() { 279 | this.newMsgDefaultEncrypt = newMsgDefaultEncrypt; 280 | function newMsgDefaultEncrypt(plaintext_buffer, phrase_buffer, cb) { 281 | var salt = self.crypto.getRandomValues(new Uint8Array(salt_byte_len)); 282 | phrase_buffer = new Uint8Array(phrase_buffer); 283 | plaintext_buffer = new Uint8Array(plaintext_buffer); 284 | defaultDeriveKey(phrase_buffer, 1000000, salt, function(key) { 285 | encrypt(key, plaintext_buffer, salt, function(encrpyted_stuff) { 286 | cb(salt.buffer, encrpyted_stuff); 287 | }); 288 | }); 289 | } 290 | this.hkdfEncrypt = hkdfEncrypt; 291 | function hkdfEncrypt(plaintext_buffer, phrase_buffer, cb) { 292 | var salt = self.crypto.getRandomValues(new Uint8Array(salt_byte_len)); 293 | phrase_buffer = new Uint8Array(phrase_buffer); 294 | plaintext_buffer = new Uint8Array(plaintext_buffer); 295 | hkdfDeriveKey(phrase_buffer, salt, function(key) { 296 | encrypt(key, plaintext_buffer, salt, function(encrpyted_stuff) { 297 | cb(salt.buffer, encrpyted_stuff); 298 | }); 299 | }); 300 | } 301 | this.hkdfDecrypt = hkdfDecrypt; 302 | function hkdfDecrypt(cipher_buff, phrase_buffer, cb) { 303 | phrase_buffer = new Uint8Array(phrase_buffer); 304 | cipher_buff = new Uint8Array(cipher_buff); 305 | var salt = cipher_buff.slice(0, salt_byte_len); 306 | cipher_buff = cipher_buff.slice(salt_byte_len); 307 | hkdfDeriveKey(phrase_buffer, salt, function(key) { 308 | noDecodeDecrypt(key, cipher_buff, salt, function(decrypted_buff) { 309 | cb(decrypted_buff); 310 | }); 311 | }); 312 | } 313 | this.encrypt = encrypt; 314 | function encrypt(key, plaintext, iv, cb, aad="") { 315 | var alg_obj = { 316 | name: "AES-GCM", 317 | iv 318 | }; 319 | if (aad != "") 320 | alg_obj.additionalData = aad; 321 | self.crypto.subtle.encrypt(alg_obj, key, plaintext).then((encrpyted_stuff)=>{ 322 | cb(encrpyted_stuff); 323 | } 324 | ); 325 | } 326 | this.noDecodeDecrypt = noDecodeDecrypt; 327 | function noDecodeDecrypt(key, ciphertext, iv, cb, aad="") { 328 | var alg_obj = { 329 | name: "AES-GCM", 330 | iv 331 | }; 332 | if (aad != "") 333 | alg_obj.additionalData = aad; 334 | self.crypto.subtle.decrypt(alg_obj, key, ciphertext).then((decrpyted_stuff)=>{ 335 | cb(decrpyted_stuff); 336 | } 337 | ).catch(function(e) { 338 | cb(null) 339 | }); 340 | } 341 | this.defaultDeriveKey = defaultDeriveKey; 342 | function defaultDeriveKey(encoded_material, iterations, salt, cb) { 343 | var alg_obj = { 344 | name: "PBKDF2", 345 | salt, 346 | iterations: iterations, 347 | hash: "SHA-512", 348 | }; 349 | var derived_for_alg = { 350 | "name": "AES-GCM", 351 | "length": 256 352 | }; 353 | self.crypto.subtle.importKey("raw", encoded_material, alg_obj.name, false, ["deriveBits", "deriveKey"]).then((key_mat)=>{ 354 | self.crypto.subtle.deriveKey(alg_obj, key_mat, derived_for_alg, true, ["encrypt", "decrypt"]).then((key)=>{ 355 | cb(key); 356 | } 357 | ); 358 | } 359 | ); 360 | } 361 | this.hkdfDeriveKey = hkdfDeriveKey; 362 | function hkdfDeriveKey(encoded_material, salt, cb) { 363 | var alg_obj = { 364 | name: "HKDF", 365 | salt, 366 | hash: "SHA-512", 367 | info: new ArrayBuffer(0), 368 | }; 369 | var derived_for_alg = { 370 | "name": "AES-GCM", 371 | "length": 256 372 | }; 373 | self.crypto.subtle.importKey("raw", encoded_material, alg_obj.name, false, ["deriveBits", "deriveKey"]).then((key_mat)=>{ 374 | self.crypto.subtle.deriveKey(alg_obj, key_mat, derived_for_alg, true, ["encrypt", "decrypt"]).then((key)=>{ 375 | cb(key); 376 | } 377 | ); 378 | } 379 | ); 380 | } 381 | this.defaultGenerateSalt = defaultGenerateSalt; 382 | function defaultGenerateSalt(size) { 383 | var hb = []; 384 | var ns = ""; 385 | for (var i = 48; i <= 122; i++) 386 | if (i < 58 || i > 97) 387 | hb.push(String.fromCodePoint(i)); 388 | for (var i = 0; i < size; i++) 389 | ns += hb[getRandomInclusive(0, (hb.length - 1))]; 390 | return ns; 391 | } 392 | this.hexToArrayBuffer = hexToArrayBuffer; 393 | function hexToArrayBuffer(hex_str, buffer_type=null) { 394 | const regex = new RegExp(/0x/i); 395 | if (regex.test(hex_str.substring(0, 2))) 396 | hex_str = hex_str.substring(2); 397 | var ret = []; 398 | for (var i = 0; i < hex_str.length / 2; i++) { 399 | var x = i * 2; 400 | const n = parseInt(hex_str.substr(x, 2), 16); 401 | ret.push(n); 402 | } 403 | if (buffer_type) 404 | return new buffer_type(ret); 405 | else 406 | return ret; 407 | } 408 | function getRandomInclusive(min, max) { 409 | return Math.floor(Math.random() * (max - min + 1)) + min; 410 | } 411 | this.generateECDHKeys = generateECDHKeys; 412 | function generateECDHKeys(callback) { 413 | self.crypto.subtle.generateKey({ 414 | name: "ECDH", 415 | namedCurve: "P-521", 416 | }, true, ["deriveKey"]).then(callback); 417 | } 418 | this.importEcdhKey = importEcdhKey; 419 | function importEcdhKey(keyData, keyType, usage, keyFormat, callback) { 420 | self.crypto.subtle.importKey(keyFormat, keyData, { 421 | name: "ECDH", 422 | namedCurve: "P-521", 423 | }, keyType !== "privateKey", usage ? [usage] : []).then(callback); 424 | } 425 | this.exportKey = exportKey; 426 | function exportKey(key, keyFormat, callback) { 427 | self.crypto.subtle.exportKey(keyFormat, key).then(callback); 428 | } 429 | this.deriveEcdhKey = deriveEcdhKey; 430 | function deriveEcdhKey(privateKey, publicKey, callback) { 431 | self.crypto.subtle.deriveKey({ 432 | name: "ECDH", 433 | public: publicKey, 434 | }, privateKey, { 435 | name: "AES-GCM", 436 | length: 256, 437 | }, true, ["encrypt", "decrypt"]).then(callback); 438 | } 439 | function preEncoder(input_msg) { 440 | var text_encoder = new TextEncoder(); 441 | if (/^base64_/i.test(input_msg)) { 442 | try { 443 | input_msg = input_msg.replace("base64_", ""); 444 | var tc = atob(input_msg); 445 | return strToUint8(tc); 446 | } catch (e) { 447 | return text_encoder.encode(input_msg); 448 | } 449 | } else 450 | return text_encoder.encode(input_msg); 451 | } 452 | } 453 | function getRandomInclusive(min, max) { 454 | return Math.floor(Math.random() * (max - min + 1)) + min; 455 | } 456 | function bufferToHex(buffer) { 457 | return [...new Uint8Array(buffer)].map(b=>b.toString(16).padStart(2, "0")).join(""); 458 | } 459 | function set_secp256k1(secp256k1) { 460 | secp_h = secp256k1; 461 | } 462 | function set_pbkdf2(pbkdf2, sha512, pbkdf2Async) {} 463 | (()=>{ 464 | "use strict"; 465 | var t = { 466 | d: (e,n)=>{ 467 | for (var r in n) 468 | t.o(n, r) && !t.o(e, r) && Object.defineProperty(e, r, { 469 | enumerable: !0, 470 | get: n[r] 471 | }) 472 | } 473 | , 474 | o: (t,e)=>Object.prototype.hasOwnProperty.call(t, e), 475 | r: t=>{ 476 | "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { 477 | value: "Module" 478 | }), 479 | Object.defineProperty(t, "__esModule", { 480 | value: !0 481 | }) 482 | } 483 | } 484 | , e = {}; 485 | function n(t) { 486 | if (!Number.isSafeInteger(t) || t < 0) 487 | throw new Error(`Wrong positive integer: ${t}`) 488 | } 489 | function r(t, ...e) { 490 | if (!(t instanceof Uint8Array)) 491 | throw new TypeError("Expected Uint8Array"); 492 | if (e.length > 0 && !e.includes(t.length)) 493 | throw new TypeError(`Expected Uint8Array of length ${e}, not of length=${t.length}`) 494 | } 495 | t.r(e), 496 | t.d(e, { 497 | bitGet: ()=>Z, 498 | bitLen: ()=>_, 499 | bitMask: ()=>j, 500 | bitSet: ()=>V, 501 | bytesToHex: ()=>L, 502 | bytesToNumberBE: ()=>T, 503 | bytesToNumberLE: ()=>q, 504 | concatBytes: ()=>k, 505 | createHmacDrbg: ()=>K, 506 | ensureBytes: ()=>C, 507 | equalBytes: ()=>P, 508 | hexToBytes: ()=>R, 509 | hexToNumber: ()=>H, 510 | numberToBytesBE: ()=>N, 511 | numberToBytesLE: ()=>D, 512 | numberToHexUnpadded: ()=>U, 513 | numberToVarBytesBE: ()=>F, 514 | utf8ToBytes: ()=>$, 515 | validateObject: ()=>W 516 | }); 517 | const i = { 518 | number: n, 519 | bool: function(t) { 520 | if ("boolean" != typeof t) 521 | throw new Error(`Expected boolean, not ${t}`) 522 | }, 523 | bytes: r, 524 | hash: function(t) { 525 | if ("function" != typeof t || "function" != typeof t.create) 526 | throw new Error("Hash should be wrapped by utils.wrapConstructor"); 527 | n(t.outputLen), 528 | n(t.blockLen) 529 | }, 530 | exists: function(t, e=!0) { 531 | if (t.destroyed) 532 | throw new Error("Hash instance has been destroyed"); 533 | if (e && t.finished) 534 | throw new Error("Hash#digest() has already been called") 535 | }, 536 | output: function(t, e) { 537 | r(t); 538 | const n = e.outputLen; 539 | if (t.length < n) 540 | throw new Error(`digestInto() expects output buffer of length at least ${n}`) 541 | } 542 | } 543 | , o = { 544 | node: void 0, 545 | web: "object" == typeof self && "crypto"in self ? self.crypto : void 0 546 | } 547 | , s = t=>new DataView(t.buffer,t.byteOffset,t.byteLength) 548 | , f = (t,e)=>t << 32 - e | t >>> e; 549 | if (68 !== new Uint8Array(new Uint32Array([287454020]).buffer)[0]) 550 | throw new Error("Non little-endian hardware is not supported"); 551 | Array.from({ 552 | length: 256 553 | }, ((t,e)=>e.toString(16).padStart(2, "0"))); 554 | const a = async()=>{} 555 | ; 556 | async function c(t, e, n) { 557 | let r = Date.now(); 558 | for (let i = 0; i < t; i++) { 559 | n(i); 560 | const t = Date.now() - r; 561 | t >= 0 && t < e || (await a(), 562 | r += t) 563 | } 564 | } 565 | function h(t) { 566 | if ("string" == typeof t && (t = function(t) { 567 | if ("string" != typeof t) 568 | throw new TypeError("utf8ToBytes expected string, got " + typeof t); 569 | return (new TextEncoder).encode(t) 570 | }(t)), 571 | !(t instanceof Uint8Array)) 572 | throw new TypeError(`Expected input type is Uint8Array (got ${typeof t})`); 573 | return t 574 | } 575 | class u { 576 | clone() { 577 | return this._cloneInto() 578 | } 579 | } 580 | const l = t=>"[object Object]" === Object.prototype.toString.call(t) && t.constructor === Object; 581 | function d(t) { 582 | const e = e=>t().update(h(e)).digest() 583 | , n = t(); 584 | return e.outputLen = n.outputLen, 585 | e.blockLen = n.blockLen, 586 | e.create = ()=>t(), 587 | e 588 | } 589 | function b(t=32) { 590 | if (o.web) 591 | return o.web.getRandomValues(new Uint8Array(t)); 592 | if (o.node) 593 | return new Uint8Array(o.node.randomBytes(t).buffer); 594 | throw new Error("The environment doesn't have randomBytes function") 595 | } 596 | class p extends u { 597 | constructor(t, e, n, r) { 598 | super(), 599 | this.blockLen = t, 600 | this.outputLen = e, 601 | this.padOffset = n, 602 | this.isLE = r, 603 | this.finished = !1, 604 | this.length = 0, 605 | this.pos = 0, 606 | this.destroyed = !1, 607 | this.buffer = new Uint8Array(t), 608 | this.view = s(this.buffer) 609 | } 610 | update(t) { 611 | i.exists(this); 612 | const {view: e, buffer: n, blockLen: r} = this 613 | , o = (t = h(t)).length; 614 | for (let i = 0; i < o; ) { 615 | const f = Math.min(r - this.pos, o - i); 616 | if (f !== r) 617 | n.set(t.subarray(i, i + f), this.pos), 618 | this.pos += f, 619 | i += f, 620 | this.pos === r && (this.process(e, 0), 621 | this.pos = 0); 622 | else { 623 | const e = s(t); 624 | for (; r <= o - i; i += r) 625 | this.process(e, i) 626 | } 627 | } 628 | return this.length += t.length, 629 | this.roundClean(), 630 | this 631 | } 632 | digestInto(t) { 633 | i.exists(this), 634 | i.output(t, this), 635 | this.finished = !0; 636 | const {buffer: e, view: n, blockLen: r, isLE: o} = this; 637 | let {pos: f} = this; 638 | e[f++] = 128, 639 | this.buffer.subarray(f).fill(0), 640 | this.padOffset > r - f && (this.process(n, 0), 641 | f = 0); 642 | for (let t = f; t < r; t++) 643 | e[t] = 0; 644 | !function(t, e, n, r) { 645 | if ("function" == typeof t.setBigUint64) 646 | return t.setBigUint64(e, n, r); 647 | const i = BigInt(32) 648 | , o = BigInt(4294967295) 649 | , s = Number(n >> i & o) 650 | , f = Number(n & o) 651 | , a = r ? 4 : 0 652 | , c = r ? 0 : 4; 653 | t.setUint32(e + a, s, r), 654 | t.setUint32(e + c, f, r) 655 | }(n, r - 8, BigInt(8 * this.length), o), 656 | this.process(n, 0); 657 | const a = s(t) 658 | , c = this.outputLen; 659 | if (c % 4) 660 | throw new Error("_sha2: outputLen should be aligned to 32bit"); 661 | const h = c / 4 662 | , u = this.get(); 663 | if (h > u.length) 664 | throw new Error("_sha2: outputLen bigger than state"); 665 | for (let t = 0; t < h; t++) 666 | a.setUint32(4 * t, u[t], o) 667 | } 668 | digest() { 669 | const {buffer: t, outputLen: e} = this; 670 | this.digestInto(t); 671 | const n = t.slice(0, e); 672 | return this.destroy(), 673 | n 674 | } 675 | _cloneInto(t) { 676 | t || (t = new this.constructor), 677 | t.set(...this.get()); 678 | const {blockLen: e, buffer: n, length: r, finished: i, destroyed: o, pos: s} = this; 679 | return t.length = r, 680 | t.pos = s, 681 | t.finished = i, 682 | t.destroyed = o, 683 | r % e && t.buffer.set(n), 684 | t 685 | } 686 | } 687 | const w = (t,e,n)=>t & e ^ t & n ^ e & n 688 | , g = new Uint32Array([1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298]) 689 | , y = new Uint32Array([1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]) 690 | , m = new Uint32Array(64); 691 | class E extends p { 692 | constructor() { 693 | super(64, 32, 8, !1), 694 | this.A = 0 | y[0], 695 | this.B = 0 | y[1], 696 | this.C = 0 | y[2], 697 | this.D = 0 | y[3], 698 | this.E = 0 | y[4], 699 | this.F = 0 | y[5], 700 | this.G = 0 | y[6], 701 | this.H = 0 | y[7] 702 | } 703 | get() { 704 | const {A: t, B: e, C: n, D: r, E: i, F: o, G: s, H: f} = this; 705 | return [t, e, n, r, i, o, s, f] 706 | } 707 | set(t, e, n, r, i, o, s, f) { 708 | this.A = 0 | t, 709 | this.B = 0 | e, 710 | this.C = 0 | n, 711 | this.D = 0 | r, 712 | this.E = 0 | i, 713 | this.F = 0 | o, 714 | this.G = 0 | s, 715 | this.H = 0 | f 716 | } 717 | process(t, e) { 718 | for (let n = 0; n < 16; n++, 719 | e += 4) 720 | m[n] = t.getUint32(e, !1); 721 | for (let t = 16; t < 64; t++) { 722 | const e = m[t - 15] 723 | , n = m[t - 2] 724 | , r = f(e, 7) ^ f(e, 18) ^ e >>> 3 725 | , i = f(n, 17) ^ f(n, 19) ^ n >>> 10; 726 | m[t] = i + m[t - 7] + r + m[t - 16] | 0 727 | } 728 | let {A: n, B: r, C: i, D: o, E: s, F: a, G: c, H: h} = this; 729 | for (let t = 0; t < 64; t++) { 730 | const e = h + (f(s, 6) ^ f(s, 11) ^ f(s, 25)) + ((u = s) & a ^ ~u & c) + g[t] + m[t] | 0 731 | , l = (f(n, 2) ^ f(n, 13) ^ f(n, 22)) + w(n, r, i) | 0; 732 | h = c, 733 | c = a, 734 | a = s, 735 | s = o + e | 0, 736 | o = i, 737 | i = r, 738 | r = n, 739 | n = e + l | 0 740 | } 741 | var u; 742 | n = n + this.A | 0, 743 | r = r + this.B | 0, 744 | i = i + this.C | 0, 745 | o = o + this.D | 0, 746 | s = s + this.E | 0, 747 | a = a + this.F | 0, 748 | c = c + this.G | 0, 749 | h = h + this.H | 0, 750 | this.set(n, r, i, o, s, a, c, h) 751 | } 752 | roundClean() { 753 | m.fill(0) 754 | } 755 | destroy() { 756 | this.set(0, 0, 0, 0, 0, 0, 0, 0), 757 | this.buffer.fill(0) 758 | } 759 | } 760 | class x extends E { 761 | constructor() { 762 | super(), 763 | this.A = -1056596264, 764 | this.B = 914150663, 765 | this.C = 812702999, 766 | this.D = -150054599, 767 | this.E = -4191439, 768 | this.F = 1750603025, 769 | this.G = 1694076839, 770 | this.H = -1090891868, 771 | this.outputLen = 28 772 | } 773 | } 774 | const B = d((()=>new E)) 775 | , A = (d((()=>new x)), 776 | BigInt(0)) 777 | , v = BigInt(1) 778 | , S = BigInt(2) 779 | , I = t=>t instanceof Uint8Array 780 | , O = Array.from({ 781 | length: 256 782 | }, ((t,e)=>e.toString(16).padStart(2, "0"))); 783 | function L(t) { 784 | if (!I(t)) 785 | throw new Error("Uint8Array expected"); 786 | let e = ""; 787 | for (let n = 0; n < t.length; n++) 788 | e += O[t[n]]; 789 | return e 790 | } 791 | function U(t) { 792 | const e = t.toString(16); 793 | return 1 & e.length ? `0${e}` : e 794 | } 795 | function H(t) { 796 | if ("string" != typeof t) 797 | throw new Error("hex string expected, got " + typeof t); 798 | return BigInt("" === t ? "0" : `0x${t}`) 799 | } 800 | function R(t) { 801 | if ("string" != typeof t) 802 | throw new Error("hex string expected, got " + typeof t); 803 | if (t.length % 2) 804 | throw new Error("hex string is invalid: unpadded " + t.length); 805 | const e = new Uint8Array(t.length / 2); 806 | for (let n = 0; n < e.length; n++) { 807 | const r = 2 * n 808 | , i = t.slice(r, r + 2) 809 | , o = Number.parseInt(i, 16); 810 | if (Number.isNaN(o) || o < 0) 811 | throw new Error("invalid byte sequence"); 812 | e[n] = o 813 | } 814 | return e 815 | } 816 | function T(t) { 817 | return H(L(t)) 818 | } 819 | function q(t) { 820 | if (!I(t)) 821 | throw new Error("Uint8Array expected"); 822 | return H(L(Uint8Array.from(t).reverse())) 823 | } 824 | const N = (t,e)=>R(t.toString(16).padStart(2 * e, "0")) 825 | , D = (t,e)=>N(t, e).reverse() 826 | , F = t=>R(U(t)); 827 | function C(t, e, n) { 828 | let r; 829 | if ("string" == typeof e) 830 | try { 831 | r = R(e) 832 | } catch (n) { 833 | throw new Error(`${t} must be valid hex string, got "${e}". Cause: ${n}`) 834 | } 835 | else { 836 | if (!I(e)) 837 | throw new Error(`${t} must be hex string or Uint8Array`); 838 | r = Uint8Array.from(e) 839 | } 840 | const i = r.length; 841 | if ("number" == typeof n && i !== n) 842 | throw new Error(`${t} expected ${n} bytes, got ${i}`); 843 | return r 844 | } 845 | function k(...t) { 846 | const e = new Uint8Array(t.reduce(((t,e)=>t + e.length), 0)); 847 | let n = 0; 848 | return t.forEach((t=>{ 849 | if (!I(t)) 850 | throw new Error("Uint8Array expected"); 851 | e.set(t, n), 852 | n += t.length 853 | } 854 | )), 855 | e 856 | } 857 | function P(t, e) { 858 | if (t.length !== e.length) 859 | return !1; 860 | for (let n = 0; n < t.length; n++) 861 | if (t[n] !== e[n]) 862 | return !1; 863 | return !0 864 | } 865 | function $(t) { 866 | if ("string" != typeof t) 867 | throw new Error("utf8ToBytes expected string, got " + typeof t); 868 | return (new TextEncoder).encode(t) 869 | } 870 | function _(t) { 871 | let e; 872 | for (e = 0; t > 0n; t >>= v, 873 | e += 1) 874 | ; 875 | return e 876 | } 877 | const Z = (t,e)=>t >> BigInt(e) & 1n 878 | , V = (t,e,n)=>t | (n ? v : A) << BigInt(e) 879 | , j = t=>(S << BigInt(t - 1)) - v 880 | , z = t=>new Uint8Array(t) 881 | , G = t=>Uint8Array.from(t); 882 | function K(t, e, n) { 883 | if ("number" != typeof t || t < 2) 884 | throw new Error("hashLen must be a number"); 885 | if ("number" != typeof e || e < 2) 886 | throw new Error("qByteLen must be a number"); 887 | if ("function" != typeof n) 888 | throw new Error("hmacFn must be a function"); 889 | let r = z(t) 890 | , i = z(t) 891 | , o = 0; 892 | const s = ()=>{ 893 | r.fill(1), 894 | i.fill(0), 895 | o = 0 896 | } 897 | , f = (...t)=>n(i, r, ...t) 898 | , a = (t=z())=>{ 899 | i = f(G([0]), t), 900 | r = f(), 901 | 0 !== t.length && (i = f(G([1]), t), 902 | r = f()) 903 | } 904 | , c = ()=>{ 905 | if (o++ >= 1e3) 906 | throw new Error("drbg: tried 1000 values"); 907 | let t = 0; 908 | const n = []; 909 | for (; t < e; ) { 910 | r = f(); 911 | const e = r.slice(); 912 | n.push(e), 913 | t += r.length 914 | } 915 | return k(...n) 916 | } 917 | ; 918 | return (t,e)=>{ 919 | let n; 920 | for (s(), 921 | a(t); !(n = e(c())); ) 922 | a(); 923 | return s(), 924 | n 925 | } 926 | } 927 | const M = { 928 | bigint: t=>"bigint" == typeof t, 929 | function: t=>"function" == typeof t, 930 | boolean: t=>"boolean" == typeof t, 931 | string: t=>"string" == typeof t, 932 | isSafeInteger: t=>Number.isSafeInteger(t), 933 | array: t=>Array.isArray(t), 934 | field: (t,e)=>e.Fp.isValid(t), 935 | hash: t=>"function" == typeof t && Number.isSafeInteger(t.outputLen) 936 | }; 937 | function W(t, e, n={}) { 938 | const r = (e,n,r)=>{ 939 | const i = M[n]; 940 | if ("function" != typeof i) 941 | throw new Error(`Invalid validator "${n}", expected function`); 942 | const o = t[e]; 943 | if (!(r && void 0 === o || i(o, t))) 944 | throw new Error(`Invalid param ${String(e)}=${o} (${typeof o}), expected ${n}`) 945 | } 946 | ; 947 | for (const [t,n] of Object.entries(e)) 948 | r(t, n, !1); 949 | for (const [t,e] of Object.entries(n)) 950 | r(t, e, !0); 951 | return t 952 | } 953 | const Y = BigInt(0) 954 | , X = BigInt(1) 955 | , J = BigInt(2) 956 | , Q = BigInt(3) 957 | , tt = BigInt(4) 958 | , et = BigInt(5) 959 | , nt = BigInt(8); 960 | function rt(t, e) { 961 | const n = t % e; 962 | return n >= Y ? n : e + n 963 | } 964 | function it(t, e, n) { 965 | if (n <= Y || e < Y) 966 | throw new Error("Expected power/modulo > 0"); 967 | if (n === X) 968 | return Y; 969 | let r = X; 970 | for (; e > Y; ) 971 | e & X && (r = r * t % n), 972 | t = t * t % n, 973 | e >>= X; 974 | return r 975 | } 976 | function ot(t, e, n) { 977 | let r = t; 978 | for (; e-- > Y; ) 979 | r *= r, 980 | r %= n; 981 | return r 982 | } 983 | function st(t, e) { 984 | if (t === Y || e <= Y) 985 | throw new Error(`invert: expected positive integers, got n=${t} mod=${e}`); 986 | let n = rt(t, e) 987 | , r = e 988 | , i = Y 989 | , o = X 990 | , s = X 991 | , f = Y; 992 | for (; n !== Y; ) { 993 | const t = r / n 994 | , e = r % n 995 | , a = i - s * t 996 | , c = o - f * t; 997 | r = n, 998 | n = e, 999 | i = s, 1000 | o = f, 1001 | s = a, 1002 | f = c 1003 | } 1004 | if (r !== X) 1005 | throw new Error("invert: does not exist"); 1006 | return rt(i, e) 1007 | } 1008 | BigInt(9), 1009 | BigInt(16); 1010 | const ft = ["create", "isValid", "is0", "neg", "inv", "sqrt", "sqr", "eql", "add", "sub", "mul", "pow", "div", "addN", "subN", "mulN", "sqrN"]; 1011 | function at(t) { 1012 | return W(t, ft.reduce(((t,e)=>(t[e] = "function", 1013 | t)), { 1014 | ORDER: "bigint", 1015 | MASK: "bigint", 1016 | BYTES: "isSafeInteger", 1017 | BITS: "isSafeInteger" 1018 | })) 1019 | } 1020 | function ct(t, e) { 1021 | const n = void 0 !== e ? e : t.toString(2).length; 1022 | return { 1023 | nBitLength: n, 1024 | nByteLength: Math.ceil(n / 8) 1025 | } 1026 | } 1027 | const ht = BigInt(0) 1028 | , ut = BigInt(1); 1029 | function lt(t) { 1030 | return at(t.Fp), 1031 | W(t, { 1032 | n: "bigint", 1033 | h: "bigint", 1034 | Gx: "field", 1035 | Gy: "field" 1036 | }, { 1037 | nBitLength: "isSafeInteger", 1038 | nByteLength: "isSafeInteger" 1039 | }), 1040 | Object.freeze({ 1041 | ...ct(t.n, t.nBitLength), 1042 | ...t 1043 | }) 1044 | } 1045 | const {bytesToNumberBE: dt, hexToBytes: bt} = e 1046 | , pt = { 1047 | Err: class extends Error { 1048 | constructor(t="") { 1049 | super(t) 1050 | } 1051 | } 1052 | , 1053 | _parseInt(t) { 1054 | const {Err: e} = pt; 1055 | if (t.length < 2 || 2 !== t[0]) 1056 | throw new e("Invalid signature integer tag"); 1057 | const n = t[1] 1058 | , r = t.subarray(2, n + 2); 1059 | if (!n || r.length !== n) 1060 | throw new e("Invalid signature integer: wrong length"); 1061 | if (0 === r[0] && r[1] <= 127) 1062 | throw new e("Invalid signature integer: trailing length"); 1063 | return { 1064 | d: dt(r), 1065 | l: t.subarray(n + 2) 1066 | } 1067 | }, 1068 | toSig(t) { 1069 | const {Err: e} = pt 1070 | , n = "string" == typeof t ? bt(t) : t; 1071 | if (!(n instanceof Uint8Array)) 1072 | throw new Error("ui8a expected"); 1073 | let r = n.length; 1074 | if (r < 2 || 48 != n[0]) 1075 | throw new e("Invalid signature tag"); 1076 | if (n[1] !== r - 2) 1077 | throw new e("Invalid signature: incorrect length"); 1078 | const {d: i, l: o} = pt._parseInt(n.subarray(2)) 1079 | , {d: s, l: f} = pt._parseInt(o); 1080 | if (f.length) 1081 | throw new e("Invalid signature: left bytes after parsing"); 1082 | return { 1083 | r: i, 1084 | s 1085 | } 1086 | }, 1087 | hexFromSig(t) { 1088 | const e = t=>Number.parseInt(t[0], 16) >= 8 ? "00" + t : t 1089 | , n = t=>{ 1090 | const e = t.toString(16); 1091 | return 1 & e.length ? `0${e}` : e 1092 | } 1093 | , r = e(n(t.s)) 1094 | , i = e(n(t.r)) 1095 | , o = r.length / 2 1096 | , s = i.length / 2 1097 | , f = n(o) 1098 | , a = n(s); 1099 | return `30${n(s + o + 4)}02${a}${i}02${f}${r}` 1100 | } 1101 | } 1102 | , wt = BigInt(0) 1103 | , gt = BigInt(1); 1104 | function yt(t) { 1105 | const e = function(t) { 1106 | const e = lt(t); 1107 | return W(e, { 1108 | hash: "hash", 1109 | hmac: "function", 1110 | randomBytes: "function" 1111 | }, { 1112 | bits2int: "function", 1113 | bits2int_modN: "function", 1114 | lowS: "boolean" 1115 | }), 1116 | Object.freeze({ 1117 | lowS: !0, 1118 | ...e 1119 | }) 1120 | }(t) 1121 | , n = e.n 1122 | , r = e.Fp 1123 | , i = r.BYTES + 1 1124 | , o = 2 * r.BYTES + 1; 1125 | function s(t) { 1126 | return rt(t, n) 1127 | } 1128 | function f(t) { 1129 | return st(t, n) 1130 | } 1131 | const {ProjectivePoint: a, normPrivateKeyToScalar: c, weierstrassEquation: h, isWithinCurveOrder: u} = function(t) { 1132 | const e = function(t) { 1133 | const e = lt(t); 1134 | W(e, { 1135 | a: "field", 1136 | b: "field", 1137 | fromBytes: "function", 1138 | toBytes: "function" 1139 | }, { 1140 | allowedPrivateKeyLengths: "array", 1141 | wrapPrivateKey: "boolean", 1142 | isTorsionFree: "function", 1143 | clearCofactor: "function", 1144 | allowInfinityPoint: "boolean" 1145 | }); 1146 | const {endo: n, Fp: r, a: i} = e; 1147 | if (n) { 1148 | if (!r.eql(i, r.ZERO)) 1149 | throw new Error("Endomorphism can only be defined for Koblitz curves that have a=0"); 1150 | if ("object" != typeof n || "bigint" != typeof n.beta || "function" != typeof n.splitScalar) 1151 | throw new Error("Expected endomorphism with beta: bigint and splitScalar: function") 1152 | } 1153 | return Object.freeze({ 1154 | ...e 1155 | }) 1156 | }(t) 1157 | , {Fp: n} = e; 1158 | function r(t) { 1159 | const {a: r, b: i} = e 1160 | , o = n.sqr(t) 1161 | , s = n.mul(o, t); 1162 | return n.add(n.add(s, n.mul(t, r)), i) 1163 | } 1164 | function i(t) { 1165 | return "bigint" == typeof t && wt < t && t < e.n 1166 | } 1167 | function o(t) { 1168 | if (!i(t)) 1169 | throw new Error("Expected valid bigint: 0 < bigint < curve.n") 1170 | } 1171 | function s(t) { 1172 | const {allowedPrivateKeyLengths: n, nByteLength: r, wrapPrivateKey: i, n: s} = e; 1173 | if (n && "bigint" != typeof t) { 1174 | if (t instanceof Uint8Array && (t = L(t)), 1175 | "string" != typeof t || !n.includes(t.length)) 1176 | throw new Error("Invalid key"); 1177 | t = t.padStart(2 * r, "0") 1178 | } 1179 | let f; 1180 | try { 1181 | f = "bigint" == typeof t ? t : T(C("private key", t, r)) 1182 | } catch (e) { 1183 | throw new Error(`private key must be ${r} bytes, hex or bigint, not ${typeof t}`) 1184 | } 1185 | return i && (f = rt(f, s)), 1186 | o(f), 1187 | f 1188 | } 1189 | const f = new Map; 1190 | function a(t) { 1191 | if (!(t instanceof c)) 1192 | throw new Error("ProjectivePoint expected") 1193 | } 1194 | class c { 1195 | constructor(t, e, r) { 1196 | if (this.px = t, 1197 | this.py = e, 1198 | this.pz = r, 1199 | null == t || !n.isValid(t)) 1200 | throw new Error("x required"); 1201 | if (null == e || !n.isValid(e)) 1202 | throw new Error("y required"); 1203 | if (null == r || !n.isValid(r)) 1204 | throw new Error("z required") 1205 | } 1206 | static fromAffine(t) { 1207 | const {x: e, y: r} = t || {}; 1208 | if (!t || !n.isValid(e) || !n.isValid(r)) 1209 | throw new Error("invalid affine point"); 1210 | if (t instanceof c) 1211 | throw new Error("projective point not allowed"); 1212 | const i = t=>n.eql(t, n.ZERO); 1213 | return i(e) && i(r) ? c.ZERO : new c(e,r,n.ONE) 1214 | } 1215 | get x() { 1216 | return this.toAffine().x 1217 | } 1218 | get y() { 1219 | return this.toAffine().y 1220 | } 1221 | static normalizeZ(t) { 1222 | const e = n.invertBatch(t.map((t=>t.pz))); 1223 | return t.map(((t,n)=>t.toAffine(e[n]))).map(c.fromAffine) 1224 | } 1225 | static fromHex(t) { 1226 | const n = c.fromAffine(e.fromBytes(C("pointHex", t))); 1227 | return n.assertValidity(), 1228 | n 1229 | } 1230 | static fromPrivateKey(t) { 1231 | return c.BASE.multiply(s(t)) 1232 | } 1233 | _setWindowSize(t) { 1234 | this._WINDOW_SIZE = t, 1235 | f.delete(this) 1236 | } 1237 | assertValidity() { 1238 | if (this.is0()) { 1239 | if (e.allowInfinityPoint) 1240 | return; 1241 | throw new Error("bad point: ZERO") 1242 | } 1243 | const {x: t, y: i} = this.toAffine(); 1244 | if (!n.isValid(t) || !n.isValid(i)) 1245 | throw new Error("bad point: x or y not FE"); 1246 | const o = n.sqr(i) 1247 | , s = r(t); 1248 | if (!n.eql(o, s)) 1249 | throw new Error("bad point: equation left !=right"); 1250 | if (!this.isTorsionFree()) 1251 | throw new Error("bad point: not in prime-order subgroup") 1252 | } 1253 | hasEvenY() { 1254 | const {y: t} = this.toAffine(); 1255 | if (n.isOdd) 1256 | return !n.isOdd(t); 1257 | throw new Error("Field doesn't support isOdd") 1258 | } 1259 | equals(t) { 1260 | a(t); 1261 | const {px: e, py: r, pz: i} = this 1262 | , {px: o, py: s, pz: f} = t 1263 | , c = n.eql(n.mul(e, f), n.mul(o, i)) 1264 | , h = n.eql(n.mul(r, f), n.mul(s, i)); 1265 | return c && h 1266 | } 1267 | negate() { 1268 | return new c(this.px,n.neg(this.py),this.pz) 1269 | } 1270 | double() { 1271 | const {a: t, b: r} = e 1272 | , i = n.mul(r, 3n) 1273 | , {px: o, py: s, pz: f} = this; 1274 | let a = n.ZERO 1275 | , h = n.ZERO 1276 | , u = n.ZERO 1277 | , l = n.mul(o, o) 1278 | , d = n.mul(s, s) 1279 | , b = n.mul(f, f) 1280 | , p = n.mul(o, s); 1281 | return p = n.add(p, p), 1282 | u = n.mul(o, f), 1283 | u = n.add(u, u), 1284 | a = n.mul(t, u), 1285 | h = n.mul(i, b), 1286 | h = n.add(a, h), 1287 | a = n.sub(d, h), 1288 | h = n.add(d, h), 1289 | h = n.mul(a, h), 1290 | a = n.mul(p, a), 1291 | u = n.mul(i, u), 1292 | b = n.mul(t, b), 1293 | p = n.sub(l, b), 1294 | p = n.mul(t, p), 1295 | p = n.add(p, u), 1296 | u = n.add(l, l), 1297 | l = n.add(u, l), 1298 | l = n.add(l, b), 1299 | l = n.mul(l, p), 1300 | h = n.add(h, l), 1301 | b = n.mul(s, f), 1302 | b = n.add(b, b), 1303 | l = n.mul(b, p), 1304 | a = n.sub(a, l), 1305 | u = n.mul(b, d), 1306 | u = n.add(u, u), 1307 | u = n.add(u, u), 1308 | new c(a,h,u) 1309 | } 1310 | add(t) { 1311 | a(t); 1312 | const {px: r, py: i, pz: o} = this 1313 | , {px: s, py: f, pz: h} = t; 1314 | let u = n.ZERO 1315 | , l = n.ZERO 1316 | , d = n.ZERO; 1317 | const b = e.a 1318 | , p = n.mul(e.b, 3n); 1319 | let w = n.mul(r, s) 1320 | , g = n.mul(i, f) 1321 | , y = n.mul(o, h) 1322 | , m = n.add(r, i) 1323 | , E = n.add(s, f); 1324 | m = n.mul(m, E), 1325 | E = n.add(w, g), 1326 | m = n.sub(m, E), 1327 | E = n.add(r, o); 1328 | let x = n.add(s, h); 1329 | return E = n.mul(E, x), 1330 | x = n.add(w, y), 1331 | E = n.sub(E, x), 1332 | x = n.add(i, o), 1333 | u = n.add(f, h), 1334 | x = n.mul(x, u), 1335 | u = n.add(g, y), 1336 | x = n.sub(x, u), 1337 | d = n.mul(b, E), 1338 | u = n.mul(p, y), 1339 | d = n.add(u, d), 1340 | u = n.sub(g, d), 1341 | d = n.add(g, d), 1342 | l = n.mul(u, d), 1343 | g = n.add(w, w), 1344 | g = n.add(g, w), 1345 | y = n.mul(b, y), 1346 | E = n.mul(p, E), 1347 | g = n.add(g, y), 1348 | y = n.sub(w, y), 1349 | y = n.mul(b, y), 1350 | E = n.add(E, y), 1351 | w = n.mul(g, E), 1352 | l = n.add(l, w), 1353 | w = n.mul(x, E), 1354 | u = n.mul(m, u), 1355 | u = n.sub(u, w), 1356 | w = n.mul(m, g), 1357 | d = n.mul(x, d), 1358 | d = n.add(d, w), 1359 | new c(u,l,d) 1360 | } 1361 | subtract(t) { 1362 | return this.add(t.negate()) 1363 | } 1364 | is0() { 1365 | return this.equals(c.ZERO) 1366 | } 1367 | wNAF(t) { 1368 | return u.wNAFCached(this, f, t, (t=>{ 1369 | const e = n.invertBatch(t.map((t=>t.pz))); 1370 | return t.map(((t,n)=>t.toAffine(e[n]))).map(c.fromAffine) 1371 | } 1372 | )) 1373 | } 1374 | multiplyUnsafe(t) { 1375 | const r = c.ZERO; 1376 | if (t === wt) 1377 | return r; 1378 | if (o(t), 1379 | t === gt) 1380 | return this; 1381 | const {endo: i} = e; 1382 | if (!i) 1383 | return u.unsafeLadder(this, t); 1384 | let {k1neg: s, k1: f, k2neg: a, k2: h} = i.splitScalar(t) 1385 | , l = r 1386 | , d = r 1387 | , b = this; 1388 | for (; f > wt || h > wt; ) 1389 | f & gt && (l = l.add(b)), 1390 | h & gt && (d = d.add(b)), 1391 | b = b.double(), 1392 | f >>= gt, 1393 | h >>= gt; 1394 | return s && (l = l.negate()), 1395 | a && (d = d.negate()), 1396 | d = new c(n.mul(d.px, i.beta),d.py,d.pz), 1397 | l.add(d) 1398 | } 1399 | multiply(t) { 1400 | o(t); 1401 | let r, i, s = t; 1402 | const {endo: f} = e; 1403 | if (f) { 1404 | const {k1neg: t, k1: e, k2neg: o, k2: a} = f.splitScalar(s); 1405 | let {p: h, f: l} = this.wNAF(e) 1406 | , {p: d, f: b} = this.wNAF(a); 1407 | h = u.constTimeNegate(t, h), 1408 | d = u.constTimeNegate(o, d), 1409 | d = new c(n.mul(d.px, f.beta),d.py,d.pz), 1410 | r = h.add(d), 1411 | i = l.add(b) 1412 | } else { 1413 | const {p: t, f: e} = this.wNAF(s); 1414 | r = t, 1415 | i = e 1416 | } 1417 | return c.normalizeZ([r, i])[0] 1418 | } 1419 | multiplyAndAddUnsafe(t, e, n) { 1420 | const r = c.BASE 1421 | , i = (t,e)=>e !== wt && e !== gt && t.equals(r) ? t.multiply(e) : t.multiplyUnsafe(e) 1422 | , o = i(this, e).add(i(t, n)); 1423 | return o.is0() ? void 0 : o 1424 | } 1425 | toAffine(t) { 1426 | const {px: e, py: r, pz: i} = this 1427 | , o = this.is0(); 1428 | null == t && (t = o ? n.ONE : n.inv(i)); 1429 | const s = n.mul(e, t) 1430 | , f = n.mul(r, t) 1431 | , a = n.mul(i, t); 1432 | if (o) 1433 | return { 1434 | x: n.ZERO, 1435 | y: n.ZERO 1436 | }; 1437 | if (!n.eql(a, n.ONE)) 1438 | throw new Error("invZ was invalid"); 1439 | return { 1440 | x: s, 1441 | y: f 1442 | } 1443 | } 1444 | isTorsionFree() { 1445 | const {h: t, isTorsionFree: n} = e; 1446 | if (t === gt) 1447 | return !0; 1448 | if (n) 1449 | return n(c, this); 1450 | throw new Error("isTorsionFree() has not been declared for the elliptic curve") 1451 | } 1452 | clearCofactor() { 1453 | const {h: t, clearCofactor: n} = e; 1454 | return t === gt ? this : n ? n(c, this) : this.multiplyUnsafe(e.h) 1455 | } 1456 | toRawBytes(t=!0) { 1457 | return this.assertValidity(), 1458 | e.toBytes(c, this, t) 1459 | } 1460 | toHex(t=!0) { 1461 | return L(this.toRawBytes(t)) 1462 | } 1463 | } 1464 | c.BASE = new c(e.Gx,e.Gy,n.ONE), 1465 | c.ZERO = new c(n.ZERO,n.ONE,n.ZERO); 1466 | const h = e.nBitLength 1467 | , u = function(t, e) { 1468 | const n = (t,e)=>{ 1469 | const n = e.negate(); 1470 | return t ? n : e 1471 | } 1472 | , r = t=>({ 1473 | windows: Math.ceil(e / t) + 1, 1474 | windowSize: 2 ** (t - 1) 1475 | }); 1476 | return { 1477 | constTimeNegate: n, 1478 | unsafeLadder(e, n) { 1479 | let r = t.ZERO 1480 | , i = e; 1481 | for (; n > ht; ) 1482 | n & ut && (r = r.add(i)), 1483 | i = i.double(), 1484 | n >>= ut; 1485 | return r 1486 | }, 1487 | precomputeWindow(t, e) { 1488 | const {windows: n, windowSize: i} = r(e) 1489 | , o = []; 1490 | let s = t 1491 | , f = s; 1492 | for (let t = 0; t < n; t++) { 1493 | f = s, 1494 | o.push(f); 1495 | for (let t = 1; t < i; t++) 1496 | f = f.add(s), 1497 | o.push(f); 1498 | s = f.double() 1499 | } 1500 | return o 1501 | }, 1502 | wNAF(e, i, o) { 1503 | const {windows: s, windowSize: f} = r(e); 1504 | let a = t.ZERO 1505 | , c = t.BASE; 1506 | const h = BigInt(2 ** e - 1) 1507 | , u = 2 ** e 1508 | , l = BigInt(e); 1509 | for (let t = 0; t < s; t++) { 1510 | const e = t * f; 1511 | let r = Number(o & h); 1512 | o >>= l, 1513 | r > f && (r -= u, 1514 | o += ut); 1515 | const s = e 1516 | , d = e + Math.abs(r) - 1 1517 | , b = t % 2 != 0 1518 | , p = r < 0; 1519 | 0 === r ? c = c.add(n(b, i[s])) : a = a.add(n(p, i[d])) 1520 | } 1521 | return { 1522 | p: a, 1523 | f: c 1524 | } 1525 | }, 1526 | wNAFCached(t, e, n, r) { 1527 | const i = t._WINDOW_SIZE || 1; 1528 | let o = e.get(t); 1529 | return o || (o = this.precomputeWindow(t, i), 1530 | 1 !== i && e.set(t, r(o))), 1531 | this.wNAF(i, o, n) 1532 | } 1533 | } 1534 | }(c, e.endo ? Math.ceil(h / 2) : h); 1535 | return { 1536 | ProjectivePoint: c, 1537 | normPrivateKeyToScalar: s, 1538 | weierstrassEquation: r, 1539 | isWithinCurveOrder: i 1540 | } 1541 | }({ 1542 | ...e, 1543 | toBytes(t, e, n) { 1544 | const i = e.toAffine() 1545 | , o = r.toBytes(i.x) 1546 | , s = k; 1547 | return n ? s(Uint8Array.from([e.hasEvenY() ? 2 : 3]), o) : s(Uint8Array.from([4]), o, r.toBytes(i.y)) 1548 | }, 1549 | fromBytes(t) { 1550 | const e = t.length 1551 | , n = t[0] 1552 | , s = t.subarray(1); 1553 | if (e !== i || 2 !== n && 3 !== n) { 1554 | if (e === o && 4 === n) 1555 | return { 1556 | x: r.fromBytes(s.subarray(0, r.BYTES)), 1557 | y: r.fromBytes(s.subarray(r.BYTES, 2 * r.BYTES)) 1558 | }; 1559 | throw new Error(`Point of length ${e} was invalid. Expected ${i} compressed bytes or ${o} uncompressed bytes`) 1560 | } 1561 | { 1562 | const t = T(s); 1563 | if (!(wt < (f = t) && f < r.ORDER)) 1564 | throw new Error("Point is not on curve"); 1565 | const e = h(t); 1566 | let i = r.sqrt(e); 1567 | return 1 == (1 & n) != ((i & gt) === gt) && (i = r.neg(i)), 1568 | { 1569 | x: t, 1570 | y: i 1571 | } 1572 | } 1573 | var f 1574 | } 1575 | }) 1576 | , l = t=>L(N(t, e.nByteLength)); 1577 | function d(t) { 1578 | return t > n >> gt 1579 | } 1580 | const b = (t,e,n)=>T(t.slice(e, n)); 1581 | class p { 1582 | constructor(t, e, n) { 1583 | this.r = t, 1584 | this.s = e, 1585 | this.recovery = n, 1586 | this.assertValidity() 1587 | } 1588 | static fromCompact(t) { 1589 | const n = e.nByteLength; 1590 | return t = C("compactSignature", t, 2 * n), 1591 | new p(b(t, 0, n),b(t, n, 2 * n)) 1592 | } 1593 | static fromDER(t) { 1594 | const {r: e, s: n} = pt.toSig(C("DER", t)); 1595 | return new p(e,n) 1596 | } 1597 | assertValidity() { 1598 | if (!u(this.r)) 1599 | throw new Error("r must be 0 < r < CURVE.n"); 1600 | if (!u(this.s)) 1601 | throw new Error("s must be 0 < s < CURVE.n") 1602 | } 1603 | addRecoveryBit(t) { 1604 | return new p(this.r,this.s,t) 1605 | } 1606 | recoverPublicKey(t) { 1607 | const {r: n, s: i, recovery: o} = this 1608 | , c = m(C("msgHash", t)); 1609 | if (null == o || ![0, 1, 2, 3].includes(o)) 1610 | throw new Error("recovery id invalid"); 1611 | const h = 2 === o || 3 === o ? n + e.n : n; 1612 | if (h >= r.ORDER) 1613 | throw new Error("recovery id 2 or 3 invalid"); 1614 | const u = 0 == (1 & o) ? "02" : "03" 1615 | , d = a.fromHex(u + l(h)) 1616 | , b = f(h) 1617 | , p = s(-c * b) 1618 | , w = s(i * b) 1619 | , g = a.BASE.multiplyAndAddUnsafe(d, p, w); 1620 | if (!g) 1621 | throw new Error("point at infinify"); 1622 | return g.assertValidity(), 1623 | g 1624 | } 1625 | hasHighS() { 1626 | return d(this.s) 1627 | } 1628 | normalizeS() { 1629 | return this.hasHighS() ? new p(this.r,s(-this.s),this.recovery) : this 1630 | } 1631 | toDERRawBytes() { 1632 | return R(this.toDERHex()) 1633 | } 1634 | toDERHex() { 1635 | return pt.hexFromSig({ 1636 | r: this.r, 1637 | s: this.s 1638 | }) 1639 | } 1640 | toCompactRawBytes() { 1641 | return R(this.toCompactHex()) 1642 | } 1643 | toCompactHex() { 1644 | return l(this.r) + l(this.s) 1645 | } 1646 | } 1647 | const w = { 1648 | isValidPrivateKey(t) { 1649 | try { 1650 | return c(t), 1651 | !0 1652 | } catch (t) { 1653 | return !1 1654 | } 1655 | }, 1656 | normPrivateKeyToScalar: c, 1657 | randomPrivateKey: ()=>{ 1658 | const t = function(t, e, n=!1) { 1659 | const r = (t = C("privateHash", t)).length 1660 | , i = ct(e).nByteLength + 8; 1661 | if (i < 24 || r < i || r > 1024) 1662 | throw new Error(`hashToPrivateScalar: expected ${i}-1024 bytes of input, got ${r}`); 1663 | return rt(n ? q(t) : T(t), e - X) + X 1664 | }(e.randomBytes(r.BYTES + 8), n); 1665 | return N(t, e.nByteLength) 1666 | } 1667 | , 1668 | precompute: (t=8,e=a.BASE)=>(e._setWindowSize(t), 1669 | e.multiply(BigInt(3)), 1670 | e) 1671 | }; 1672 | function g(t) { 1673 | const e = t instanceof Uint8Array 1674 | , n = "string" == typeof t 1675 | , r = (e || n) && t.length; 1676 | return e ? r === i || r === o : n ? r === 2 * i || r === 2 * o : t instanceof a 1677 | } 1678 | const y = e.bits2int || function(t) { 1679 | const n = T(t) 1680 | , r = 8 * t.length - e.nBitLength; 1681 | return r > 0 ? n >> BigInt(r) : n 1682 | } 1683 | , m = e.bits2int_modN || function(t) { 1684 | return s(y(t)) 1685 | } 1686 | , E = j(e.nBitLength); 1687 | function x(t) { 1688 | if ("bigint" != typeof t) 1689 | throw new Error("bigint expected"); 1690 | if (!(wt <= t && t < E)) 1691 | throw new Error(`bigint expected < 2^${e.nBitLength}`); 1692 | return N(t, e.nByteLength) 1693 | } 1694 | const B = { 1695 | lowS: e.lowS, 1696 | prehash: !1 1697 | } 1698 | , A = { 1699 | lowS: e.lowS, 1700 | prehash: !1 1701 | }; 1702 | return a.BASE._setWindowSize(8), 1703 | { 1704 | CURVE: e, 1705 | getPublicKey: function(t, e=!0) { 1706 | return a.fromPrivateKey(t).toRawBytes(e) 1707 | }, 1708 | getSharedSecret: function(t, e, n=!0) { 1709 | if (g(t)) 1710 | throw new Error("first arg must be private key"); 1711 | if (!g(e)) 1712 | throw new Error("second arg must be public key"); 1713 | return a.fromHex(e).multiply(c(t)).toRawBytes(n) 1714 | }, 1715 | sign: function(t, n, i=B) { 1716 | const {seed: o, k2sig: h} = function(t, n, i=B) { 1717 | if (["recovered", "canonical"].some((t=>t in i))) 1718 | throw new Error("sign() legacy options not supported"); 1719 | const {hash: o, randomBytes: h} = e; 1720 | let {lowS: l, prehash: b, extraEntropy: g} = i; 1721 | null == l && (l = !0), 1722 | t = C("msgHash", t), 1723 | b && (t = C("prehashed msgHash", o(t))); 1724 | const E = m(t) 1725 | , A = c(n) 1726 | , v = [x(A), x(E)]; 1727 | if (null != g) { 1728 | const t = !0 === g ? h(r.BYTES) : g; 1729 | v.push(C("extraEntropy", t, r.BYTES)) 1730 | } 1731 | const S = k(...v) 1732 | , I = E; 1733 | return { 1734 | seed: S, 1735 | k2sig: function(t) { 1736 | const e = y(t); 1737 | if (!u(e)) 1738 | return; 1739 | const n = f(e) 1740 | , r = a.BASE.multiply(e).toAffine() 1741 | , i = s(r.x); 1742 | if (i === wt) 1743 | return; 1744 | const o = T(w.randomPrivateKey()) 1745 | , c = f(o) 1746 | , h = s(o * A * i) 1747 | , b = s(o * I) 1748 | , g = s(c * s(h + b)) 1749 | , m = s(n * g); 1750 | if (m === wt) 1751 | return; 1752 | let E = (r.x === i ? 0 : 2) | Number(r.y & gt) 1753 | , x = m; 1754 | return l && d(m) && (x = function(t) { 1755 | return d(t) ? s(-t) : t 1756 | }(m), 1757 | E ^= 1), 1758 | new p(i,x,E) 1759 | } 1760 | } 1761 | }(t, n, i); 1762 | return K(e.hash.outputLen, e.nByteLength, e.hmac)(o, h) 1763 | }, 1764 | verify: function(t, n, r, i=A) { 1765 | const o = t; 1766 | if (n = C("msgHash", n), 1767 | r = C("publicKey", r), 1768 | "strict"in i) 1769 | throw new Error("options.strict was renamed to lowS"); 1770 | const {lowS: c, prehash: h} = i; 1771 | let u, l; 1772 | try { 1773 | if ("string" == typeof o || o instanceof Uint8Array) 1774 | try { 1775 | u = p.fromDER(o) 1776 | } catch (t) { 1777 | if (!(t instanceof pt.Err)) 1778 | throw t; 1779 | u = p.fromCompact(o) 1780 | } 1781 | else { 1782 | if ("object" != typeof o || "bigint" != typeof o.r || "bigint" != typeof o.s) 1783 | throw new Error("PARSE"); 1784 | { 1785 | const {r: t, s: e} = o; 1786 | u = new p(t,e) 1787 | } 1788 | } 1789 | l = a.fromHex(r) 1790 | } catch (t) { 1791 | if ("PARSE" === t.message) 1792 | throw new Error("signature must be Signature instance, Uint8Array or hex string"); 1793 | return !1 1794 | } 1795 | if (c && u.hasHighS()) 1796 | return !1; 1797 | h && (n = e.hash(n)); 1798 | const {r: d, s: b} = u 1799 | , w = m(n) 1800 | , g = f(b) 1801 | , y = s(w * g) 1802 | , E = s(d * g) 1803 | , x = a.BASE.multiplyAndAddUnsafe(l, y, E)?.toAffine(); 1804 | return !!x && s(x.x) === d 1805 | }, 1806 | ProjectivePoint: a, 1807 | Signature: p, 1808 | utils: w 1809 | } 1810 | } 1811 | const mt = T; 1812 | function Et(t, e) { 1813 | if (t < 0 || t >= 1 << 8 * e) 1814 | throw new Error(`bad I2OSP call: value=${t} length=${e}`); 1815 | const n = Array.from({ 1816 | length: e 1817 | }).fill(0); 1818 | for (let r = e - 1; r >= 0; r--) 1819 | n[r] = 255 & t, 1820 | t >>>= 8; 1821 | return new Uint8Array(n) 1822 | } 1823 | function xt(t, e) { 1824 | const n = new Uint8Array(t.length); 1825 | for (let r = 0; r < t.length; r++) 1826 | n[r] = t[r] ^ e[r]; 1827 | return n 1828 | } 1829 | function Bt(t) { 1830 | if (!(t instanceof Uint8Array)) 1831 | throw new Error("Uint8Array expected") 1832 | } 1833 | function At(t) { 1834 | if (!Number.isSafeInteger(t)) 1835 | throw new Error("number expected") 1836 | } 1837 | function vt(t, e, n) { 1838 | const {p: r, k: i, m: o, hash: s, expand: f, DST: a} = n; 1839 | Bt(t), 1840 | At(e); 1841 | const c = function(t) { 1842 | if (t instanceof Uint8Array) 1843 | return t; 1844 | if ("string" == typeof t) 1845 | return $(t); 1846 | throw new Error("DST must be Uint8Array or string") 1847 | }(a) 1848 | , h = r.toString(2).length 1849 | , u = Math.ceil((h + i) / 8) 1850 | , l = e * o * u; 1851 | let d; 1852 | if ("xmd" === f) 1853 | d = function(t, e, n, r) { 1854 | Bt(t), 1855 | Bt(e), 1856 | At(n), 1857 | e.length > 255 && (e = r(k($("H2C-OVERSIZE-DST-"), e))); 1858 | const {outputLen: i, blockLen: o} = r 1859 | , s = Math.ceil(n / i); 1860 | if (s > 255) 1861 | throw new Error("Invalid xmd length"); 1862 | const f = k(e, Et(e.length, 1)) 1863 | , a = Et(0, o) 1864 | , c = Et(n, 2) 1865 | , h = new Array(s) 1866 | , u = r(k(a, t, c, Et(0, 1), f)); 1867 | h[0] = r(k(u, Et(1, 1), f)); 1868 | for (let t = 1; t <= s; t++) { 1869 | const e = [xt(u, h[t - 1]), Et(t + 1, 1), f]; 1870 | h[t] = r(k(...e)) 1871 | } 1872 | return k(...h).slice(0, n) 1873 | }(t, c, l, s); 1874 | else if ("xof" === f) 1875 | d = function(t, e, n, r, i) { 1876 | if (Bt(t), 1877 | Bt(e), 1878 | At(n), 1879 | e.length > 255) { 1880 | const t = Math.ceil(2 * r / 8); 1881 | e = i.create({ 1882 | dkLen: t 1883 | }).update($("H2C-OVERSIZE-DST-")).update(e).digest() 1884 | } 1885 | if (n > 65535 || e.length > 255) 1886 | throw new Error("expand_message_xof: invalid lenInBytes"); 1887 | return i.create({ 1888 | dkLen: n 1889 | }).update(t).update(Et(n, 2)).update(e).update(Et(e.length, 1)).digest() 1890 | }(t, c, l, i, s); 1891 | else { 1892 | if (void 0 !== f) 1893 | throw new Error('expand must be "xmd", "xof" or undefined'); 1894 | d = t 1895 | } 1896 | const b = new Array(e); 1897 | for (let t = 0; t < e; t++) { 1898 | const e = new Array(o); 1899 | for (let n = 0; n < o; n++) { 1900 | const i = u * (n + t * o) 1901 | , s = d.subarray(i, i + u); 1902 | e[n] = rt(mt(s), r) 1903 | } 1904 | b[t] = e 1905 | } 1906 | return b 1907 | } 1908 | class St extends u { 1909 | constructor(t, e) { 1910 | super(), 1911 | this.finished = !1, 1912 | this.destroyed = !1, 1913 | i.hash(t); 1914 | const n = h(e); 1915 | if (this.iHash = t.create(), 1916 | "function" != typeof this.iHash.update) 1917 | throw new TypeError("Expected instance of class which extends utils.Hash"); 1918 | this.blockLen = this.iHash.blockLen, 1919 | this.outputLen = this.iHash.outputLen; 1920 | const r = this.blockLen 1921 | , o = new Uint8Array(r); 1922 | o.set(n.length > r ? t.create().update(n).digest() : n); 1923 | for (let t = 0; t < o.length; t++) 1924 | o[t] ^= 54; 1925 | this.iHash.update(o), 1926 | this.oHash = t.create(); 1927 | for (let t = 0; t < o.length; t++) 1928 | o[t] ^= 106; 1929 | this.oHash.update(o), 1930 | o.fill(0) 1931 | } 1932 | update(t) { 1933 | return i.exists(this), 1934 | this.iHash.update(t), 1935 | this 1936 | } 1937 | digestInto(t) { 1938 | i.exists(this), 1939 | i.bytes(t, this.outputLen), 1940 | this.finished = !0, 1941 | this.iHash.digestInto(t), 1942 | this.oHash.update(t), 1943 | this.oHash.digestInto(t), 1944 | this.destroy() 1945 | } 1946 | digest() { 1947 | const t = new Uint8Array(this.oHash.outputLen); 1948 | return this.digestInto(t), 1949 | t 1950 | } 1951 | _cloneInto(t) { 1952 | t || (t = Object.create(Object.getPrototypeOf(this), {})); 1953 | const {oHash: e, iHash: n, finished: r, destroyed: i, blockLen: o, outputLen: s} = this; 1954 | return t.finished = r, 1955 | t.destroyed = i, 1956 | t.blockLen = o, 1957 | t.outputLen = s, 1958 | t.oHash = e._cloneInto(t.oHash), 1959 | t.iHash = n._cloneInto(t.iHash), 1960 | t 1961 | } 1962 | destroy() { 1963 | this.destroyed = !0, 1964 | this.oHash.destroy(), 1965 | this.iHash.destroy() 1966 | } 1967 | } 1968 | const It = (t,e,n)=>new St(t,e).update(n).digest(); 1969 | function Ot(t) { 1970 | return { 1971 | hash: t, 1972 | hmac: (e,...n)=>It(t, e, function(...t) { 1973 | if (!t.every((t=>t instanceof Uint8Array))) 1974 | throw new Error("Uint8Array list expected"); 1975 | if (1 === t.length) 1976 | return t[0]; 1977 | const e = t.reduce(((t,e)=>t + e.length), 0) 1978 | , n = new Uint8Array(e); 1979 | for (let e = 0, r = 0; e < t.length; e++) { 1980 | const i = t[e]; 1981 | n.set(i, r), 1982 | r += i.length 1983 | } 1984 | return n 1985 | }(...n)), 1986 | randomBytes: b 1987 | } 1988 | } 1989 | It.create = (t,e)=>new St(t,e); 1990 | const Lt = BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f") 1991 | , Ut = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") 1992 | , Ht = BigInt(1) 1993 | , Rt = BigInt(2) 1994 | , Tt = (t,e)=>(t + e / Rt) / e; 1995 | function qt(t) { 1996 | const e = Lt 1997 | , n = BigInt(3) 1998 | , r = BigInt(6) 1999 | , i = BigInt(11) 2000 | , o = BigInt(22) 2001 | , s = BigInt(23) 2002 | , f = BigInt(44) 2003 | , a = BigInt(88) 2004 | , c = t * t * t % e 2005 | , h = c * c * t % e 2006 | , u = ot(h, n, e) * h % e 2007 | , l = ot(u, n, e) * h % e 2008 | , d = ot(l, Rt, e) * c % e 2009 | , b = ot(d, i, e) * d % e 2010 | , p = ot(b, o, e) * b % e 2011 | , w = ot(p, f, e) * p % e 2012 | , g = ot(w, a, e) * w % e 2013 | , y = ot(g, f, e) * p % e 2014 | , m = ot(y, n, e) * h % e 2015 | , E = ot(m, s, e) * b % e 2016 | , x = ot(E, r, e) * c % e 2017 | , B = ot(x, Rt, e); 2018 | if (!Nt.eql(Nt.sqr(B), t)) 2019 | throw new Error("Cannot find square root"); 2020 | return B 2021 | } 2022 | const Nt = function(t, e, n=!1, r={}) { 2023 | if (t <= Y) 2024 | throw new Error(`Expected Fp ORDER > 0, got ${t}`); 2025 | const {nBitLength: i, nByteLength: o} = ct(t, e); 2026 | if (o > 2048) 2027 | throw new Error("Field lengths over 2048 bytes are not supported"); 2028 | const s = function(t) { 2029 | if (t % tt === Q) { 2030 | const e = (t + X) / tt; 2031 | return function(t, n) { 2032 | const r = t.pow(n, e); 2033 | if (!t.eql(t.sqr(r), n)) 2034 | throw new Error("Cannot find square root"); 2035 | return r 2036 | } 2037 | } 2038 | if (t % nt === et) { 2039 | const e = (t - et) / nt; 2040 | return function(t, n) { 2041 | const r = t.mul(n, J) 2042 | , i = t.pow(r, e) 2043 | , o = t.mul(n, i) 2044 | , s = t.mul(t.mul(o, J), i) 2045 | , f = t.mul(o, t.sub(s, t.ONE)); 2046 | if (!t.eql(t.sqr(f), n)) 2047 | throw new Error("Cannot find square root"); 2048 | return f 2049 | } 2050 | } 2051 | return function(t) { 2052 | const e = (t - X) / J; 2053 | let n, r, i; 2054 | for (n = t - X, 2055 | r = 0; n % J === Y; n /= J, 2056 | r++) 2057 | ; 2058 | for (i = J; i < t && it(i, e, t) !== t - X; i++) 2059 | ; 2060 | if (1 === r) { 2061 | const e = (t + X) / tt; 2062 | return function(t, n) { 2063 | const r = t.pow(n, e); 2064 | if (!t.eql(t.sqr(r), n)) 2065 | throw new Error("Cannot find square root"); 2066 | return r 2067 | } 2068 | } 2069 | const o = (n + X) / J; 2070 | return function(t, s) { 2071 | if (t.pow(s, e) === t.neg(t.ONE)) 2072 | throw new Error("Cannot find square root"); 2073 | let f = r 2074 | , a = t.pow(t.mul(t.ONE, i), n) 2075 | , c = t.pow(s, o) 2076 | , h = t.pow(s, n); 2077 | for (; !t.eql(h, t.ONE); ) { 2078 | if (t.eql(h, t.ZERO)) 2079 | return t.ZERO; 2080 | let e = 1; 2081 | for (let n = t.sqr(h); e < f && !t.eql(n, t.ONE); e++) 2082 | n = t.sqr(n); 2083 | const n = t.pow(a, X << BigInt(f - e - 1)); 2084 | a = t.sqr(n), 2085 | c = t.mul(c, n), 2086 | h = t.mul(h, a), 2087 | f = e 2088 | } 2089 | return c 2090 | } 2091 | }(t) 2092 | }(t) 2093 | , f = Object.freeze({ 2094 | ORDER: t, 2095 | BITS: i, 2096 | BYTES: o, 2097 | MASK: j(i), 2098 | ZERO: Y, 2099 | ONE: X, 2100 | create: e=>rt(e, t), 2101 | isValid: e=>{ 2102 | if ("bigint" != typeof e) 2103 | throw new Error("Invalid field element: expected bigint, got " + typeof e); 2104 | return Y <= e && e < t 2105 | } 2106 | , 2107 | is0: t=>t === Y, 2108 | isOdd: t=>(t & X) === X, 2109 | neg: e=>rt(-e, t), 2110 | eql: (t,e)=>t === e, 2111 | sqr: e=>rt(e * e, t), 2112 | add: (e,n)=>rt(e + n, t), 2113 | sub: (e,n)=>rt(e - n, t), 2114 | mul: (e,n)=>rt(e * n, t), 2115 | pow: (t,e)=>function(t, e, n) { 2116 | if (n < Y) 2117 | throw new Error("Expected power > 0"); 2118 | if (n === Y) 2119 | return t.ONE; 2120 | if (n === X) 2121 | return e; 2122 | let r = t.ONE 2123 | , i = e; 2124 | for (; n > Y; ) 2125 | n & X && (r = t.mul(r, i)), 2126 | i = t.sqr(i), 2127 | n >>= 1n; 2128 | return r 2129 | }(f, t, e), 2130 | div: (e,n)=>rt(e * st(n, t), t), 2131 | sqrN: t=>t * t, 2132 | addN: (t,e)=>t + e, 2133 | subN: (t,e)=>t - e, 2134 | mulN: (t,e)=>t * e, 2135 | inv: e=>st(e, t), 2136 | sqrt: r.sqrt || (t=>s(f, t)), 2137 | invertBatch: t=>function(t, e) { 2138 | const n = new Array(e.length) 2139 | , r = e.reduce(((e,r,i)=>t.is0(r) ? e : (n[i] = e, 2140 | t.mul(e, r))), t.ONE) 2141 | , i = t.inv(r); 2142 | return e.reduceRight(((e,r,i)=>t.is0(r) ? e : (n[i] = t.mul(e, n[i]), 2143 | t.mul(e, r))), i), 2144 | n 2145 | }(f, t), 2146 | cmov: (t,e,n)=>n ? e : t, 2147 | toBytes: t=>n ? D(t, o) : N(t, o), 2148 | fromBytes: t=>{ 2149 | if (t.length !== o) 2150 | throw new Error(`Fp.fromBytes: expected ${o}, got ${t.length}`); 2151 | return n ? q(t) : T(t) 2152 | } 2153 | }); 2154 | return Object.freeze(f) 2155 | }(Lt, void 0, void 0, { 2156 | sqrt: qt 2157 | }) 2158 | , Dt = function(t, e) { 2159 | const n = e=>yt({ 2160 | ...t, 2161 | ...Ot(e) 2162 | }); 2163 | return Object.freeze({ 2164 | ...n(e), 2165 | create: n 2166 | }) 2167 | }({ 2168 | a: BigInt(0), 2169 | b: BigInt(7), 2170 | Fp: Nt, 2171 | n: Ut, 2172 | Gx: BigInt("55066263022277343669578718895168534326250603453777594175500187360389116729240"), 2173 | Gy: BigInt("32670510020758816978083085130507043184471273380659243275938904335757337482424"), 2174 | h: BigInt(1), 2175 | lowS: !0, 2176 | endo: { 2177 | beta: BigInt("0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"), 2178 | splitScalar: t=>{ 2179 | const e = Ut 2180 | , n = BigInt("0x3086d221a7d46bcde86c90e49284eb15") 2181 | , r = -Ht * BigInt("0xe4437ed6010e88286f547fa90abfe4c3") 2182 | , i = BigInt("0x114ca50f7a8e2f3f657c1108d9d44cfd8") 2183 | , o = n 2184 | , s = BigInt("0x100000000000000000000000000000000") 2185 | , f = Tt(o * t, e) 2186 | , a = Tt(-r * t, e); 2187 | let c = rt(t - f * n - a * i, e) 2188 | , h = rt(-f * r - a * o, e); 2189 | const u = c > s 2190 | , l = h > s; 2191 | if (u && (c = e - c), 2192 | l && (h = e - h), 2193 | c > s || h > s) 2194 | throw new Error("splitScalar: Endomorphism failed, k=" + t); 2195 | return { 2196 | k1neg: u, 2197 | k1: c, 2198 | k2neg: l, 2199 | k2: h 2200 | } 2201 | } 2202 | } 2203 | }, B); 2204 | BigInt(0); 2205 | Dt.ProjectivePoint; 2206 | Dt.utils.randomPrivateKey; 2207 | const Ft = function(t, e) { 2208 | const n = e.map((t=>Array.from(t).reverse())); 2209 | return (e,r)=>{ 2210 | const [i,o,s,f] = n.map((n=>n.reduce(((n,r)=>t.add(t.mul(n, e), r))))); 2211 | return e = t.div(i, o), 2212 | r = t.mul(r, t.div(s, f)), 2213 | { 2214 | x: e, 2215 | y: r 2216 | } 2217 | } 2218 | }(Nt, [["0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7", "0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581", "0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262", "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c"], ["0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b", "0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14", "0x0000000000000000000000000000000000000000000000000000000000000001"], ["0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c", "0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3", "0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931", "0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84"], ["0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b", "0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573", "0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f", "0x0000000000000000000000000000000000000000000000000000000000000001"]].map((t=>t.map((t=>BigInt(t)))))) 2219 | , Ct = function(t, e) { 2220 | if (at(t), 2221 | !t.isValid(e.A) || !t.isValid(e.B) || !t.isValid(e.Z)) 2222 | throw new Error("mapToCurveSimpleSWU: invalid opts"); 2223 | const n = function(t, e) { 2224 | const n = t.ORDER; 2225 | let r = 0n; 2226 | for (let t = n - 1n; t % 2n === 0n; t /= 2n) 2227 | r += 1n; 2228 | const i = r 2229 | , o = (n - 1n) / 2n ** i 2230 | , s = (o - 1n) / 2n 2231 | , f = 2n ** i - 1n 2232 | , a = 2n ** (i - 1n) 2233 | , c = t.pow(e, o) 2234 | , h = t.pow(e, (o + 1n) / 2n); 2235 | let u = (e,n)=>{ 2236 | let r = c 2237 | , o = t.pow(n, f) 2238 | , u = t.sqr(o); 2239 | u = t.mul(u, n); 2240 | let l = t.mul(e, u); 2241 | l = t.pow(l, s), 2242 | l = t.mul(l, o), 2243 | o = t.mul(l, n), 2244 | u = t.mul(l, e); 2245 | let d = t.mul(u, o); 2246 | l = t.pow(d, a); 2247 | let b = t.eql(l, t.ONE); 2248 | o = t.mul(u, h), 2249 | l = t.mul(d, r), 2250 | u = t.cmov(o, u, b), 2251 | d = t.cmov(l, d, b); 2252 | for (let e = i; e > 1; e--) { 2253 | let n = 2n ** (e - 2n) 2254 | , i = t.pow(d, n); 2255 | const s = t.eql(i, t.ONE); 2256 | o = t.mul(u, r), 2257 | r = t.mul(r, r), 2258 | i = t.mul(d, r), 2259 | u = t.cmov(o, u, s), 2260 | d = t.cmov(i, d, s) 2261 | } 2262 | return { 2263 | isValid: b, 2264 | value: u 2265 | } 2266 | } 2267 | ; 2268 | if (t.ORDER % 4n === 3n) { 2269 | const n = (t.ORDER - 3n) / 4n 2270 | , r = t.sqrt(t.neg(e)); 2271 | u = (e,i)=>{ 2272 | let o = t.sqr(i); 2273 | const s = t.mul(e, i); 2274 | o = t.mul(o, s); 2275 | let f = t.pow(o, n); 2276 | f = t.mul(f, s); 2277 | const a = t.mul(f, r) 2278 | , c = t.mul(t.sqr(f), i) 2279 | , h = t.eql(c, e); 2280 | return { 2281 | isValid: h, 2282 | value: t.cmov(a, f, h) 2283 | } 2284 | } 2285 | } 2286 | return u 2287 | }(t, e.Z); 2288 | if (!t.isOdd) 2289 | throw new Error("Fp.isOdd is not implemented!"); 2290 | return r=>{ 2291 | let i, o, s, f, a, c, h, u; 2292 | i = t.sqr(r), 2293 | i = t.mul(i, e.Z), 2294 | o = t.sqr(i), 2295 | o = t.add(o, i), 2296 | s = t.add(o, t.ONE), 2297 | s = t.mul(s, e.B), 2298 | f = t.cmov(e.Z, t.neg(o), !t.eql(o, t.ZERO)), 2299 | f = t.mul(f, e.A), 2300 | o = t.sqr(s), 2301 | c = t.sqr(f), 2302 | a = t.mul(c, e.A), 2303 | o = t.add(o, a), 2304 | o = t.mul(o, s), 2305 | c = t.mul(c, f), 2306 | a = t.mul(c, e.B), 2307 | o = t.add(o, a), 2308 | h = t.mul(i, s); 2309 | const {isValid: l, value: d} = n(o, c); 2310 | u = t.mul(i, r), 2311 | u = t.mul(u, d), 2312 | h = t.cmov(h, s, l), 2313 | u = t.cmov(u, d, l); 2314 | const b = t.isOdd(r) === t.isOdd(u); 2315 | return u = t.cmov(t.neg(u), u, b), 2316 | h = t.div(h, f), 2317 | { 2318 | x: h, 2319 | y: u 2320 | } 2321 | } 2322 | }(Nt, { 2323 | A: BigInt("0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533"), 2324 | B: BigInt("1771"), 2325 | Z: Nt.create(BigInt("-11")) 2326 | }) 2327 | , {hashToCurve: kt, encodeToCurve: Pt} = function(t, e, n) { 2328 | return W(n, { 2329 | DST: "string", 2330 | p: "bigint", 2331 | m: "isSafeInteger", 2332 | k: "isSafeInteger", 2333 | hash: "hash" 2334 | }), 2335 | { 2336 | hashToCurve(r, i) { 2337 | const o = vt(r, 2, { 2338 | ...n, 2339 | DST: n.DST, 2340 | ...i 2341 | }) 2342 | , s = t.fromAffine(e(o[0])) 2343 | , f = t.fromAffine(e(o[1])) 2344 | , a = s.add(f).clearCofactor(); 2345 | return a.assertValidity(), 2346 | a 2347 | }, 2348 | encodeToCurve(r, i) { 2349 | const o = vt(r, 1, { 2350 | ...n, 2351 | DST: n.encodeDST, 2352 | ...i 2353 | }) 2354 | , s = t.fromAffine(e(o[0])).clearCofactor(); 2355 | return s.assertValidity(), 2356 | s 2357 | } 2358 | } 2359 | }(Dt.ProjectivePoint, (t=>{ 2360 | const {x: e, y: n} = Ct(Nt.create(t[0])); 2361 | return Ft(e, n) 2362 | } 2363 | ), { 2364 | DST: "secp256k1_XMD:SHA-256_SSWU_RO_", 2365 | encodeDST: "secp256k1_XMD:SHA-256_SSWU_NU_", 2366 | p: Nt.ORDER, 2367 | m: 1, 2368 | k: 128, 2369 | expand: "xmd", 2370 | hash: B 2371 | }); 2372 | function $t(t, e, n, r) { 2373 | i.hash(t); 2374 | const o = function(t, e) { 2375 | if (void 0 !== e && ("object" != typeof e || !l(e))) 2376 | throw new TypeError("Options should be object or undefined"); 2377 | return Object.assign({ 2378 | dkLen: 32, 2379 | asyncTick: 10 2380 | }, e) 2381 | }(0, r) 2382 | , {c: s, dkLen: f, asyncTick: a} = o; 2383 | if (i.number(s), 2384 | i.number(f), 2385 | i.number(a), 2386 | s < 1) 2387 | throw new Error("PBKDF2: iterations (c) should be >=1"); 2388 | const c = h(e) 2389 | , u = h(n) 2390 | , d = new Uint8Array(f) 2391 | , b = It.create(t, c) 2392 | , p = b._cloneInto().update(u); 2393 | return { 2394 | c: s, 2395 | dkLen: f, 2396 | asyncTick: a, 2397 | DK: d, 2398 | PRF: b, 2399 | PRFSalt: p 2400 | } 2401 | } 2402 | function _t(t, e, n, r, i) { 2403 | return t.destroy(), 2404 | e.destroy(), 2405 | r && r.destroy(), 2406 | i.fill(0), 2407 | n 2408 | } 2409 | const Zt = BigInt(2 ** 32 - 1) 2410 | , Vt = BigInt(32); 2411 | function jt(t, e=!1) { 2412 | return e ? { 2413 | h: Number(t & Zt), 2414 | l: Number(t >> Vt & Zt) 2415 | } : { 2416 | h: 0 | Number(t >> Vt & Zt), 2417 | l: 0 | Number(t & Zt) 2418 | } 2419 | } 2420 | const zt = function(t, e=!1) { 2421 | let n = new Uint32Array(t.length) 2422 | , r = new Uint32Array(t.length); 2423 | for (let i = 0; i < t.length; i++) { 2424 | const {h: o, l: s} = jt(t[i], e); 2425 | [n[i],r[i]] = [o, s] 2426 | } 2427 | return [n, r] 2428 | } 2429 | , Gt = (t,e,n)=>t >>> n 2430 | , Kt = (t,e,n)=>t << 32 - n | e >>> n 2431 | , Mt = (t,e,n)=>t >>> n | e << 32 - n 2432 | , Wt = (t,e,n)=>t << 32 - n | e >>> n 2433 | , Yt = (t,e,n)=>t << 64 - n | e >>> n - 32 2434 | , Xt = (t,e,n)=>t >>> n - 32 | e << 64 - n 2435 | , Jt = function(t, e, n, r) { 2436 | const i = (e >>> 0) + (r >>> 0); 2437 | return { 2438 | h: t + n + (i / 2 ** 32 | 0) | 0, 2439 | l: 0 | i 2440 | } 2441 | } 2442 | , Qt = (t,e,n)=>(t >>> 0) + (e >>> 0) + (n >>> 0) 2443 | , te = (t,e,n,r)=>e + n + r + (t / 2 ** 32 | 0) | 0 2444 | , ee = (t,e,n,r)=>(t >>> 0) + (e >>> 0) + (n >>> 0) + (r >>> 0) 2445 | , ne = (t,e,n,r,i)=>e + n + r + i + (t / 2 ** 32 | 0) | 0 2446 | , re = (t,e,n,r,i,o)=>e + n + r + i + o + (t / 2 ** 32 | 0) | 0 2447 | , ie = (t,e,n,r,i)=>(t >>> 0) + (e >>> 0) + (n >>> 0) + (r >>> 0) + (i >>> 0) 2448 | , [oe,se] = zt(["0x428a2f98d728ae22", "0x7137449123ef65cd", "0xb5c0fbcfec4d3b2f", "0xe9b5dba58189dbbc", "0x3956c25bf348b538", "0x59f111f1b605d019", "0x923f82a4af194f9b", "0xab1c5ed5da6d8118", "0xd807aa98a3030242", "0x12835b0145706fbe", "0x243185be4ee4b28c", "0x550c7dc3d5ffb4e2", "0x72be5d74f27b896f", "0x80deb1fe3b1696b1", "0x9bdc06a725c71235", "0xc19bf174cf692694", "0xe49b69c19ef14ad2", "0xefbe4786384f25e3", "0x0fc19dc68b8cd5b5", "0x240ca1cc77ac9c65", "0x2de92c6f592b0275", "0x4a7484aa6ea6e483", "0x5cb0a9dcbd41fbd4", "0x76f988da831153b5", "0x983e5152ee66dfab", "0xa831c66d2db43210", "0xb00327c898fb213f", "0xbf597fc7beef0ee4", "0xc6e00bf33da88fc2", "0xd5a79147930aa725", "0x06ca6351e003826f", "0x142929670a0e6e70", "0x27b70a8546d22ffc", "0x2e1b21385c26c926", "0x4d2c6dfc5ac42aed", "0x53380d139d95b3df", "0x650a73548baf63de", "0x766a0abb3c77b2a8", "0x81c2c92e47edaee6", "0x92722c851482353b", "0xa2bfe8a14cf10364", "0xa81a664bbc423001", "0xc24b8b70d0f89791", "0xc76c51a30654be30", "0xd192e819d6ef5218", "0xd69906245565a910", "0xf40e35855771202a", "0x106aa07032bbd1b8", "0x19a4c116b8d2d0c8", "0x1e376c085141ab53", "0x2748774cdf8eeb99", "0x34b0bcb5e19b48a8", "0x391c0cb3c5c95a63", "0x4ed8aa4ae3418acb", "0x5b9cca4f7763e373", "0x682e6ff3d6b2b8a3", "0x748f82ee5defb2fc", "0x78a5636f43172f60", "0x84c87814a1f0ab72", "0x8cc702081a6439ec", "0x90befffa23631e28", "0xa4506cebde82bde9", "0xbef9a3f7b2c67915", "0xc67178f2e372532b", "0xca273eceea26619c", "0xd186b8c721c0c207", "0xeada7dd6cde0eb1e", "0xf57d4f7fee6ed178", "0x06f067aa72176fba", "0x0a637dc5a2c898a6", "0x113f9804bef90dae", "0x1b710b35131c471b", "0x28db77f523047d84", "0x32caab7b40c72493", "0x3c9ebe0a15c9bebc", "0x431d67c49c100d4c", "0x4cc5d4becb3e42b6", "0x597f299cfc657e2a", "0x5fcb6fab3ad6faec", "0x6c44198c4a475817"].map((t=>BigInt(t)))) 2449 | , fe = new Uint32Array(80) 2450 | , ae = new Uint32Array(80); 2451 | class ce extends p { 2452 | constructor() { 2453 | super(128, 64, 16, !1), 2454 | this.Ah = 1779033703, 2455 | this.Al = -205731576, 2456 | this.Bh = -1150833019, 2457 | this.Bl = -2067093701, 2458 | this.Ch = 1013904242, 2459 | this.Cl = -23791573, 2460 | this.Dh = -1521486534, 2461 | this.Dl = 1595750129, 2462 | this.Eh = 1359893119, 2463 | this.El = -1377402159, 2464 | this.Fh = -1694144372, 2465 | this.Fl = 725511199, 2466 | this.Gh = 528734635, 2467 | this.Gl = -79577749, 2468 | this.Hh = 1541459225, 2469 | this.Hl = 327033209 2470 | } 2471 | get() { 2472 | const {Ah: t, Al: e, Bh: n, Bl: r, Ch: i, Cl: o, Dh: s, Dl: f, Eh: a, El: c, Fh: h, Fl: u, Gh: l, Gl: d, Hh: b, Hl: p} = this; 2473 | return [t, e, n, r, i, o, s, f, a, c, h, u, l, d, b, p] 2474 | } 2475 | set(t, e, n, r, i, o, s, f, a, c, h, u, l, d, b, p) { 2476 | this.Ah = 0 | t, 2477 | this.Al = 0 | e, 2478 | this.Bh = 0 | n, 2479 | this.Bl = 0 | r, 2480 | this.Ch = 0 | i, 2481 | this.Cl = 0 | o, 2482 | this.Dh = 0 | s, 2483 | this.Dl = 0 | f, 2484 | this.Eh = 0 | a, 2485 | this.El = 0 | c, 2486 | this.Fh = 0 | h, 2487 | this.Fl = 0 | u, 2488 | this.Gh = 0 | l, 2489 | this.Gl = 0 | d, 2490 | this.Hh = 0 | b, 2491 | this.Hl = 0 | p 2492 | } 2493 | process(t, e) { 2494 | for (let n = 0; n < 16; n++, 2495 | e += 4) 2496 | fe[n] = t.getUint32(e), 2497 | ae[n] = t.getUint32(e += 4); 2498 | for (let t = 16; t < 80; t++) { 2499 | const e = 0 | fe[t - 15] 2500 | , n = 0 | ae[t - 15] 2501 | , r = Mt(e, n, 1) ^ Mt(e, n, 8) ^ Gt(e, n, 7) 2502 | , i = Wt(e, n, 1) ^ Wt(e, n, 8) ^ Kt(e, n, 7) 2503 | , o = 0 | fe[t - 2] 2504 | , s = 0 | ae[t - 2] 2505 | , f = Mt(o, s, 19) ^ Yt(o, s, 61) ^ Gt(o, s, 6) 2506 | , a = Wt(o, s, 19) ^ Xt(o, s, 61) ^ Kt(o, s, 6) 2507 | , c = ee(i, a, ae[t - 7], ae[t - 16]) 2508 | , h = ne(c, r, f, fe[t - 7], fe[t - 16]); 2509 | fe[t] = 0 | h, 2510 | ae[t] = 0 | c 2511 | } 2512 | let {Ah: n, Al: r, Bh: i, Bl: o, Ch: s, Cl: f, Dh: a, Dl: c, Eh: h, El: u, Fh: l, Fl: d, Gh: b, Gl: p, Hh: w, Hl: g} = this; 2513 | for (let t = 0; t < 80; t++) { 2514 | const e = Mt(h, u, 14) ^ Mt(h, u, 18) ^ Yt(h, u, 41) 2515 | , y = Wt(h, u, 14) ^ Wt(h, u, 18) ^ Xt(h, u, 41) 2516 | , m = h & l ^ ~h & b 2517 | , E = ie(g, y, u & d ^ ~u & p, se[t], ae[t]) 2518 | , x = re(E, w, e, m, oe[t], fe[t]) 2519 | , B = 0 | E 2520 | , A = Mt(n, r, 28) ^ Yt(n, r, 34) ^ Yt(n, r, 39) 2521 | , v = Wt(n, r, 28) ^ Xt(n, r, 34) ^ Xt(n, r, 39) 2522 | , S = n & i ^ n & s ^ i & s 2523 | , I = r & o ^ r & f ^ o & f; 2524 | w = 0 | b, 2525 | g = 0 | p, 2526 | b = 0 | l, 2527 | p = 0 | d, 2528 | l = 0 | h, 2529 | d = 0 | u, 2530 | ({h, l: u} = Jt(0 | a, 0 | c, 0 | x, 0 | B)), 2531 | a = 0 | s, 2532 | c = 0 | f, 2533 | s = 0 | i, 2534 | f = 0 | o, 2535 | i = 0 | n, 2536 | o = 0 | r; 2537 | const O = Qt(B, v, I); 2538 | n = te(O, x, A, S), 2539 | r = 0 | O 2540 | } 2541 | ({h: n, l: r} = Jt(0 | this.Ah, 0 | this.Al, 0 | n, 0 | r)), 2542 | ({h: i, l: o} = Jt(0 | this.Bh, 0 | this.Bl, 0 | i, 0 | o)), 2543 | ({h: s, l: f} = Jt(0 | this.Ch, 0 | this.Cl, 0 | s, 0 | f)), 2544 | ({h: a, l: c} = Jt(0 | this.Dh, 0 | this.Dl, 0 | a, 0 | c)), 2545 | ({h, l: u} = Jt(0 | this.Eh, 0 | this.El, 0 | h, 0 | u)), 2546 | ({h: l, l: d} = Jt(0 | this.Fh, 0 | this.Fl, 0 | l, 0 | d)), 2547 | ({h: b, l: p} = Jt(0 | this.Gh, 0 | this.Gl, 0 | b, 0 | p)), 2548 | ({h: w, l: g} = Jt(0 | this.Hh, 0 | this.Hl, 0 | w, 0 | g)), 2549 | this.set(n, r, i, o, s, f, a, c, h, u, l, d, b, p, w, g) 2550 | } 2551 | roundClean() { 2552 | fe.fill(0), 2553 | ae.fill(0) 2554 | } 2555 | destroy() { 2556 | this.buffer.fill(0), 2557 | this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 2558 | } 2559 | } 2560 | class he extends ce { 2561 | constructor() { 2562 | super(), 2563 | this.Ah = -1942145080, 2564 | this.Al = 424955298, 2565 | this.Bh = 1944164710, 2566 | this.Bl = -1982016298, 2567 | this.Ch = 502970286, 2568 | this.Cl = 855612546, 2569 | this.Dh = 1738396948, 2570 | this.Dl = 1479516111, 2571 | this.Eh = 258812777, 2572 | this.El = 2077511080, 2573 | this.Fh = 2011393907, 2574 | this.Fl = 79989058, 2575 | this.Gh = 1067287976, 2576 | this.Gl = 1780299464, 2577 | this.Hh = 286451373, 2578 | this.Hl = -1848208735, 2579 | this.outputLen = 28 2580 | } 2581 | } 2582 | class ue extends ce { 2583 | constructor() { 2584 | super(), 2585 | this.Ah = 573645204, 2586 | this.Al = -64227540, 2587 | this.Bh = -1621794909, 2588 | this.Bl = -934517566, 2589 | this.Ch = 596883563, 2590 | this.Cl = 1867755857, 2591 | this.Dh = -1774684391, 2592 | this.Dl = 1497426621, 2593 | this.Eh = -1775747358, 2594 | this.El = -1467023389, 2595 | this.Fh = -1101128155, 2596 | this.Fl = 1401305490, 2597 | this.Gh = 721525244, 2598 | this.Gl = 746961066, 2599 | this.Hh = 246885852, 2600 | this.Hl = -2117784414, 2601 | this.outputLen = 32 2602 | } 2603 | } 2604 | class le extends ce { 2605 | constructor() { 2606 | super(), 2607 | this.Ah = -876896931, 2608 | this.Al = -1056596264, 2609 | this.Bh = 1654270250, 2610 | this.Bl = 914150663, 2611 | this.Ch = -1856437926, 2612 | this.Cl = 812702999, 2613 | this.Dh = 355462360, 2614 | this.Dl = -150054599, 2615 | this.Eh = 1731405415, 2616 | this.El = -4191439, 2617 | this.Fh = -1900787065, 2618 | this.Fl = 1750603025, 2619 | this.Gh = -619958771, 2620 | this.Gl = 1694076839, 2621 | this.Hh = 1203062813, 2622 | this.Hl = -1090891868, 2623 | this.outputLen = 48 2624 | } 2625 | } 2626 | const de = d((()=>new ce)); 2627 | d((()=>new he)), 2628 | d((()=>new ue)), 2629 | d((()=>new le)), 2630 | set_secp256k1(Dt), 2631 | set_pbkdf2((function(t, e, n, r) { 2632 | const {c: i, dkLen: o, DK: f, PRF: a, PRFSalt: c} = $t(t, e, n, r); 2633 | let h; 2634 | const u = new Uint8Array(4) 2635 | , l = s(u) 2636 | , d = new Uint8Array(a.outputLen); 2637 | for (let t = 1, e = 0; e < o; t++, 2638 | e += a.outputLen) { 2639 | const n = f.subarray(e, e + a.outputLen); 2640 | l.setInt32(0, t, !1), 2641 | (h = c._cloneInto(h)).update(u).digestInto(d), 2642 | n.set(d.subarray(0, n.length)); 2643 | for (let t = 1; t < i; t++) { 2644 | a._cloneInto(h).update(d).digestInto(d); 2645 | for (let t = 0; t < n.length; t++) 2646 | n[t] ^= d[t] 2647 | } 2648 | } 2649 | return _t(a, c, f, h, d) 2650 | } 2651 | ), de, (async function(t, e, n, r) { 2652 | const {c: i, dkLen: o, asyncTick: f, DK: a, PRF: h, PRFSalt: u} = $t(t, e, n, r); 2653 | let l; 2654 | const d = new Uint8Array(4) 2655 | , b = s(d) 2656 | , p = new Uint8Array(h.outputLen); 2657 | for (let t = 1, e = 0; e < o; t++, 2658 | e += h.outputLen) { 2659 | const n = a.subarray(e, e + h.outputLen); 2660 | b.setInt32(0, t, !1), 2661 | (l = u._cloneInto(l)).update(d).digestInto(p), 2662 | n.set(p.subarray(0, n.length)), 2663 | await c(i - 1, f, (t=>{ 2664 | h._cloneInto(l).update(p).digestInto(p); 2665 | for (let t = 0; t < n.length; t++) 2666 | n[t] ^= p[t] 2667 | } 2668 | )) 2669 | } 2670 | return _t(h, u, a, l, p) 2671 | } 2672 | )) 2673 | } 2674 | )(); 2675 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | BitNote License: 2 | License text copyright © 2023 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc. 3 | 4 | Parameters 5 | 6 | ------------------ 7 | 8 | Licensor: Rockwell Ventures Inc. 9 | 10 | Licensed Work: BitNote 11 | 12 | Additional Use Grant: Any uses listed and defined at BitNote.xyz 13 | 14 | Change Date: The earlier of May 1st, 2028 or a date specified at BitNote.xyz/terms 15 | 16 | Change License: GNU General Public License v3.0 or later 17 | 18 | ------------------ 19 | 20 | Terms 21 | The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. 22 | 23 | Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. 24 | 25 | If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. 26 | 27 | All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. 28 | 29 | You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. 30 | 31 | Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. 32 | 33 | This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark “Business Source License”, as long as you comply with the Covenants of Licensor below. 34 | 35 | Covenants of Licensor 36 | In consideration of the right to use this License’s text and the “Business Source License” name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: 37 | 38 | To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. 39 | To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text “None” to specify a Change Date. Not to modify this License in any other way. 40 | 41 | Notice 42 | The Business Source License (this document, or the “License”) is not an Open Source license. However, the Licensed Work will eventually be made available under an Open Source License, as stated in this License. 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔒 BitNote 2 | 3 | **Protect Your Secrets. Forever.** 4 | Ultra-secure notes powered by blockchain. 5 | 🔗 [bitnote.xyz](https://bitnote.xyz) 6 | 7 |

8 | BitNote Hero Image 9 |

10 | 11 | --- 12 | 13 | ### ✅ Why BitNote 14 | 15 | BitNote is built for people who want to store sensitive information without trusting big tech, subscriptions, or centralized servers. It’s like a fireproof vault that lives on the blockchain — without the hardware or the hassle. It's great for passwords, private keys, seedphrases, or other sensitive text data. 16 | 17 | - **✔️ Strong Security** 18 | “Military Grade” encryption to keep your secrets safe. 19 | 20 | - **✔️ No Recurring Fees** 21 | Pay once, no subscriptions. 22 | 23 | - **✔️ Zero Knowledge & E2E Encrypted** 24 | Only you can see your data. 25 | 26 | - **✔️ Decentralized** 27 | No one can delete or block your access. 28 | 29 | - **✔️ Truly Private** 30 | No tracking, no personal data collection. 31 | 32 | - **✔️ Transparent Source Code** 33 | Audit everything, trust nothing. 34 | 35 | - **✔️ Built to Last** 36 | No bloat, no frameworks, engineered for longevity. 37 | 38 | - **✔️ Access Anywhere** 39 | No sync, no setup. 40 | 41 | - **⏳ Succession (In Development)** 42 | Pass down your data automatically if something happens to you. 43 | 44 | --- 45 | 46 | ### ⚙️ How It Works 47 | 48 | 1. **Create Secure Notes**: Write your notes in the BitNote app. Your data is encrypted locally before being stored on the blockchain. 49 | 50 | 2. **Access Anywhere**: Retrieve your encrypted notes from any device with a browser. Decryption happens locally, ensuring privacy. 51 | 52 | 3. **Sharing & Succession**: Securely share notes with other BitNote users or set up succession rules to pass on your secrets under specific conditions. 53 | 54 | --- 55 | 56 | ### 🪧 Sign Up 57 | 58 | After tapping [sign up](https://app.bitnote.xyz/?sign_up), you’ll be asked to create a unique username. Then you'll be presented with options on how you'd like to secure your account (either master password or security key). You’ll also be asked to fund your account to register your username and create notes on the blockchain. You can pay using crypto, credit, debit, or Apple Pay. You DO NOT need crypto to use BitNote. Once signed up, to access your encrypted notes just sign into BitNote with your credentials. 59 | 60 | --- 61 | 62 | ### 💵 Pricing 63 | 64 | BitNote is a “pay as you go” system. No subscriptions or recurring fees. You pay only to create/edit/delete notes, and viewing notes is free. 65 | 66 | Setup typically costs under $1. Creating notes costs about ~$0.005 each — making it affordable even for thousands of notes. 67 | 68 | --- 69 | 70 | ### 🌍 Use Cases 71 | 72 | - Passwords 73 | - Recovery codes 74 | - Private keys 75 | - Crypto seed phrases 76 | - Personal notes, ideas, and secrets meant to last 77 | - Deadbox or dead man’s switch - storing information that you want passed down in case something happens to you. 78 | - Digital treasure hunt - leave clues that lead people to the username and password that decrypts a BitNote account and reveals a prize. 79 | - Private Journal - use BitNote as a diary that you can optionally pass down to future generations. 80 | - Digital time capsule - create messages or store information intended to be accessed or opened far into the future. 81 | 82 | --- 83 | 84 | ### ✨ Features 85 | 86 | | Feature | Description | Status | 87 | |--------|-------------|--------| 88 | | **Sharing** | Share your notes safely and easily with other BitNote users. | ✅ Available | 89 | | **Local Client** | Run a copy of BitNote locally so you don’t have to rely on the website. | ✅ Available | 90 | | **Cold Wallet Generator** | Easily create and store “cold” crypto wallets for long-term digital asset storage. | ✅ Available | 91 | | **Import & Export** | Import and export your notes freely — your data is never locked in. | ✅ Available | 92 | | **Keyboard Shortcuts** | Quickly search, create, and save notes using keyboard shortcuts. | ✅ Available | 93 | | **Mobile App** | Use BitNote as a mobile app via your browser’s "Add to Homescreen" function. | ✅ Available | 94 | | **Password & Passphrase Generator** | Quickly create secure passwords and passphrases | ✅ Available | 95 | | **Referral System** | Earn 30% of protocol fees your referrals generate — automatically, forever. | ✅ Available | 96 | | **Security Key Support** | Supports secure login via hardware keys (e.g., YubiKeys). | ✅ Available | 97 | | **Secure Search** | Quickly search across your notes securely. | ✅ Available | 98 | | **Offline Mode** | Use BitNote even while you're fully offline. | ✅ Available | 99 | | **Secure Updater** | BitNote website updates are default opt-in, protecting you from supply chain attacks. | ✅ Available | 100 | | **Code Alert** | Automatic notification of code tampering, protecting you from supply chain attacks. | ✅ Available | 101 | | **Backup Keys** | Add unlimited backup hardware security keys to access your account | ✅ Available | 102 | | **Fiat Onramp** | Pay with Credit/Debit/Apple Pay | ✅ Available | 103 | | **Decentralized App** | The entire app will be hosted on-chain for full decentralization. | 🕒 Partially Complete | 104 | | **Succession** | Pass down your data automatically if something happens to you | 🕒 Upcoming | 105 | 106 | --- 107 | 108 | ### 📺 Screenshots 109 | 110 |

111 | Home screen 112 | Note view 113 |

114 | 115 | --- 116 | 117 | ### 🧱 Technical Overview 118 | 119 | BitNote runs entirely in your browser on a client/blockchain model. Your notes are encrypted locally using AES-256 through the web crypto API and stored on-chain. Only you (and those you explicitly authorize) can decrypt it. No centralized servers. It's just you, your browser, and the blockchain. 120 | 121 | For additional security, BitNote can be locally installed as a progressive web app on both desktop and mobile, can run offline, and requires explicit user opt-in for updates. 122 | 123 | - **Frontend**: Pure HTML/CSS/JS — no frameworks, under 1MB 124 | - **Backend**: Smart contracts written in Solidity hosted on the Avalanche blockchain (C-Chain) 125 | - **Encryption**: AES-256 using the WebCrypto API, with a browser-based zero-knowledge architecture that supports full offline mode 126 | - **Loading**: The core portions of the app load directly from the blockchain itself for stronger levels of decentralization and security 127 | 128 | --- 129 | 130 | ### ♾️ Forever Machine 131 | 132 | One of the eventual goals of BitNote is to create a "Forever Machine" - an app that can live directly on the blockchain and do its job without fear of ever disappearing. Ultimately, BitNote is a protocol, not a company. The system is designed to minimize points of failure and to last for many years. 133 | 134 | --- 135 | 136 | ### 🔐 How the Encryption Works 137 | 138 | BitNote is end-to-end encrypted and zero knowledge. All encryption happens locally on your machine, and no one can see your data besides you. 139 | 140 | After a user selects a username and master password, an account is generated with a secp256k1 key pair, EVM public address, and an ECDH p-521 key pair which is used for encrypting notes. 141 | 142 | The master password is used to derive a key with pbkdf2-sha512 set to 1 million iterations, which is then used to encrypt the two private keys with AES-GCM using the outputted 256-bit key. 143 | 144 | With the user’s public address as the index, the two private keys are encrypted on the blockchain, as well as the ECDH public key. 145 | 146 | The username is hashed with keccak256 and the resulting hash is used as an index that points to the public address. 147 | 148 | When the user logs into BitNote, the keys are retrieved, decrypted client side, and the ECDH key pair are utilized to decrypt the notes. 149 | 150 | For additional security, all the client side computation is handled within a web worker. 151 | 152 | > 🛡️ For added protection, **all cryptographic operations are run inside a web worker**, isolating them from the main thread. 153 | 154 | --- 155 | 156 | ### 🚨 Advanced Protection 157 | 158 | BitNote has a number of advanced features that help protect you, including: 159 | 160 | 1. **Opt-In Updates**: BitNote updates are explicitly opt-in, meaning that you have to accept them before they happen. This gives you the opportunity to check to make sure the update is safe before applying it. 161 |

162 | BitNote Update Bar 163 |

164 | 165 | 2. **Code Alert**: BitNote has a built in system to alert you if the version you have cached locally does not match what is being served to you through the web. This helps protect you against "supply chain attacks." If you ever see this alert come up on your app, please send a message through email/X/telegram and check BitNote's social channels to see if there is a legitimate reason for this before continuing to use the app. 166 |

167 | BitNote Alert Bar 168 |

169 | 170 | 3. **Cost to Crack**: If you choose to secure your account with a master password, we estimate your password strength with a “cost to crack” calculation that estimates how much an attacker would have to spend in compute resources to brute force your password. 171 |

172 | BitNote Alert Bar 173 |

174 | 175 | --- 176 | 177 | ### 📜 Smart Contracts 178 | 179 | - **`mod_contract.sol`** – Main contract for the app, used to authorize others. 180 | [View on Snowtrace](https://snowtrace.io/address/0x225AFdEb639E4cB7A128e348898A02e4730F2F2A) 181 | 182 | - **`better_notes_contract.sol`** – Stores user notes. 183 | [View on Snowtrace](https://snowtrace.io/address/0x3B0f15DAB71e3C609EcbB4c99e3AD7EA6532c8c9) 184 | 185 | - **`sec_keys.sol`** – Stores user security keys. 186 | [View on Snowtrace](https://snowtrace.io/address/0x78D35C5341f9625f6eC7C497Ed875E0dEE0Ef3Ac) 187 | 188 | - **`authed_contract.sol`** – Inherited by the others to manage shared auth and variables. 189 | 190 | --- 191 | 192 | ### 🧩 Source Files & Hashes 193 | 194 | These are the files that power BitNote, along with their SHA-256 hashes and links to verify integrity. [Generate hashes here.](https://app.bitnote.xyz/pages/hash_checker256/) 195 | 196 | ### 🔼 Launch Scripts 197 | - **[`index_inline.js`](https://app.bitnote.xyz/pages/js/index_inline.js)** – Inlined JavaScript that initializes the app 198 | `sha256-9f3K+SH47nSVfeCKjM/VYYBzHHgS46+NQJuU9oIp6nY=` 199 | 200 | ### 🔐 Encryption Engine 201 | - **[`ww.js`](https://app.bitnote.xyz/pages/js/ww.js)** – Handles all encryption; runs in a dedicated web worker. Loads directly from the blockchain. 202 | `sha256-G1MiiPq/7Q46PppJHATljkf7tf8ln23NyFwUIjW91Pg=` 203 | 204 | ### 🌐 Service Layer 205 | - **[`sw.js`](https://app.bitnote.xyz/sw.js)** – Service worker used for PWA support and request interception. Loads directly from the blockchain. 206 | `sha256-1uBYQMtnqb8J7BynjBqu8M9McU88ATeloN9PZsbqcvU=` 207 | 208 | ### 🧱 App Core 209 | - **[`legacy_app.js`](https://app.bitnote.xyz/pages/js/legacy_app.js)** – The primary application logic and UI handling. Loads directly from the blockchain. 210 | `sha256-Nh9vxnofc31FBRHUJL8fbXDrF4p5K9Q11fdhOPZugUs=` 211 | 212 | ### 🔐 Password Utilities 213 | - **[`zxcvbn.js`](https://app.bitnote.xyz/pages/js/zxcvbn.js)** – Password strength estimator 214 | `sha256-FxuQZMMw/XFXhJnDHbjZcaFeiASfpTqEw0HPl5je6tg=` 215 | 216 | - **[`new_wl.js`](https://app.bitnote.xyz/pages/js/new_wl.js)** – Expanded wordlist for generating secure passphrases 217 | `sha256-iZzF53dvnO//nREcmPhEgwO9G/5Mq7UU8oihLCNltoo=` 218 | 219 | ### 🎨 Styling 220 | - **[`index_inline.css`](https://app.bitnote.xyz/pages/css/index_inline.css)** – Critical CSS loaded with the main page 221 | `sha256-cNpabiKA16hSe3b3kmJzD2KUTljZLFPCTEe+2/6dZ8c=` 222 | 223 | - **[`legacy_app.css`](https://app.bitnote.xyz/pages/css/legacy_app.css)** – Remaining styles used across the app. Loads directly from the blockchain. 224 | `sha256-Qh+toqfaD45xkc+pd3HKOTjXwdYyRefN8mhrnjgnYas=` 225 | 226 | ### 🛡️ Raw Content Security Policy Header 227 | 228 | - `default-src 'self'; connect-src 'self' https://api.avax-test.network https://ava-testnet.public.blastapi.io https://api.avax.network https://avalanche-c-chain-rpc.publicnode.com https://avax.meowrpc.com https://endpoints.omniatech.io https://1rpc.io https://api.coinbase.com; script-src 'strict-dynamic' 'sha256-9f3K+SH47nSVfeCKjM/VYYBzHHgS46+NQJuU9oIp6nY=' 'sha256-G1MiiPq/7Q46PppJHATljkf7tf8ln23NyFwUIjW91Pg=' 'sha256-1uBYQMtnqb8J7BynjBqu8M9McU88ATeIoN9PZsbqcvU=' 'sha256-Nh9vxnofc31FBRHUJL8fbXDrF4p5K9Q11fdhOPZugUs=' 'sha256-FxuQZMMw/XFXhJnDHbjZcaFeiASfpTqEw0HPl5je6tg=' 'sha256-iZzF53dvnO//nREcmPhEgwO9G/5Mg7UU8oihLCNItoo='; style-src 'sha256-cNpabiKA16hSe3b3kmJzD2KUTljZLFPCTEe+2/6dZ8c=' 'sha256-Qh+toqfaD45xkc+pd3HKOTjXwdYyRefN8mhrnjgnYas=';worker-src 'self' blob:;img-src 'self' data:;` 229 | 230 | - `sha256-GtQnJ0eyKFJCKBM7Gv2TToW1Vu0JsCoDfjcHY6WILSg=` 231 | 232 | --- 233 | 234 | ### 🔍 Is BitNote Audited? 235 | 236 | Yes. BitNote has been audited by Cure53, a very reputable cybersecurity firm. 237 | 238 | - [Summary of the Audit](https://app.bitnote.xyz/pages/docs/rve-01-summary.pdf) 239 | - [Full Audit Report](https://app.bitnote.xyz/pages/docs/rve-01-report_final.pdf) 240 | 241 | --- 242 | 243 | ### 🫥 What Happens if BitNote Disappears? 244 | 245 | Your data is stored on the blockchain, not on BitNote. The BitNote app allows you to easily access your data on the blockchain, but there are multiple ways to do that if the BitNote website disappears, including: 246 | - Using the locally installable version of BitNote 247 | - Using the built in secure export feature to access your raw data 248 | - Communicating directly with the smart contracts to pull your data 249 | - Accessing your data directly from a blockchain explorer 250 | - Using an alternative front end 251 | 252 | Because BitNote's code is openly available, if it ever goes down it can be re-created fairly easily. 253 | 254 | For more FAQs, see the [BitNote website](https://bitnote.xyz). 255 | 256 | --- 257 | 258 | ### ⛓️‍💥 Why did we choose the AVAX C-Chain as our blockchain? 259 | 260 | The AVAX C-Chain has a great combination of qualities: 261 | 262 | 1. It's fairly decentralized with ~1,500 validators 263 | 2. Transactions are inexpensive 264 | 3. It's EVM compatible 265 | 4. It has very fast finality, so you can save notes quickly 266 | 5. It's very reliable, and has basically no down time or outages 267 | 268 | --- 269 | 270 | ### 🔐 License 271 | 272 | BitNote is licensed under BSL 1.1. It will automatically trigger an open source transition to GPL v3.0 on **May 1, 2028**. 273 | [Read the full license](https://bitnote.xyz/license) 274 | 275 | --- 276 | 277 | ### 🌐 Visit BitNote 278 | 279 | [https://bitnote.xyz](https://bitnote.xyz) 280 | 281 | -------------------------------------------------------------------------------- /authed_contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8; 3 | 4 | interface OwnedContract { 5 | function auth_addr() external view returns (address); 6 | } 7 | 8 | contract authed_contract{ 9 | OwnedContract private contract_owner; 10 | 11 | constructor(address init_contract_owner){ 12 | contract_owner = OwnedContract(init_contract_owner); 13 | } 14 | 15 | receive() external payable {} 16 | 17 | modifier confirmValue(){ 18 | require(msg.value >= ((((gasleft()*(tx.gasprice/1e9))*1e9)/100) * taxRate())); 19 | _; 20 | } 21 | 22 | modifier authCall(){ 23 | require(msg.sender == address(contract_owner) || msg.sender == contract_owner.auth_addr()); 24 | _; 25 | } 26 | 27 | modifier requireOwnership(bytes32 index){ 28 | require (getAddressLink(index) == msg.sender); 29 | _; 30 | } 31 | 32 | function migrateModContract(address new_addr) external authCall { 33 | contract_owner = OwnedContract(new_addr); 34 | } 35 | 36 | function authPayout(uint256 amount) external authCall { 37 | payable(address(contract_owner)).transfer(amount); 38 | } 39 | 40 | function authPayoutFull() external authCall { 41 | payable(address(contract_owner)).transfer(address(this).balance); 42 | } 43 | 44 | function taxRate() internal view returns (uint256) { 45 | (, bytes memory data) = address(contract_owner).staticcall(abi.encodeWithSignature("tax_rate()")); 46 | return abi.decode(data, (uint256)); 47 | } 48 | 49 | function basePrice() internal view returns (uint256) { 50 | (,bytes memory data) = address(contract_owner).staticcall(abi.encodeWithSignature("base_price()")); 51 | return abi.decode(data, (uint256)); 52 | } 53 | 54 | function getAddressLink(bytes32 index) internal view returns (address){ 55 | (, bytes memory data) = address(contract_owner).staticcall(abi.encodeWithSignature("getAddressLink(bytes32)", index)); 56 | return abi.decode(data, (address)); 57 | } 58 | 59 | function getReferrer() internal view returns (address){ 60 | (, bytes memory data) = address(contract_owner).staticcall(abi.encodeWithSignature("getReferrer(address)", msg.sender)); 61 | return abi.decode(data, (address)); 62 | } 63 | 64 | function refPayout() internal confirmValue { 65 | address ref = getReferrer(); 66 | if(ref != 0x0000000000000000000000000000000000000000) 67 | payable(ref).transfer(((msg.value / 100)*30)); 68 | } 69 | 70 | function stdPayout() internal confirmValue { 71 | payable(address(contract_owner)).transfer(msg.value); 72 | } 73 | 74 | function getContractOwner() external view returns(address){ 75 | return address(contract_owner); 76 | } 77 | } -------------------------------------------------------------------------------- /better_notes_contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8; 3 | 4 | import "./authed_contract.sol"; 5 | 6 | contract better_notes_contract is authed_contract { 7 | mapping(bytes32 => bytes) private indexed_space; 8 | mapping(bytes32 => address) private owner_index; 9 | mapping(address => bytes32[]) private users_index; 10 | mapping(address => uint256) private last_update; 11 | 12 | mapping(bytes32 => address) private transfer_index; 13 | 14 | constructor(address init_auth_contract) authed_contract(init_auth_contract){} 15 | 16 | modifier payRef(){ 17 | refPayout(); 18 | updateInternal(); 19 | _; 20 | } 21 | 22 | modifier requireOwner(bytes32 index){ 23 | require(owner_index[index] == msg.sender); 24 | _; 25 | } 26 | 27 | function updateInternal() internal { 28 | last_update[msg.sender] = block.timestamp; 29 | } 30 | 31 | function setIndexBytes(bytes32 index, bytes calldata data) internal { 32 | require(indexed_space[index].length == 0 || owner_index[index] == msg.sender); 33 | indexed_space[index] = data; 34 | if(owner_index[index] != msg.sender) 35 | owner_index[index] = msg.sender; 36 | } 37 | 38 | function clearIndexBytes(bytes32 index) internal { 39 | indexed_space[index] = ""; 40 | owner_index[index] = 0x0000000000000000000000000000000000000000; 41 | } 42 | 43 | function deleteUserIndexAtPos(uint256 pos) internal { 44 | users_index[msg.sender][pos] = users_index[msg.sender][users_index[msg.sender].length - 1]; 45 | users_index[msg.sender].pop(); 46 | } 47 | 48 | function setUserBytes(bytes32 index, bytes calldata data) external payable payRef{ 49 | setIndexBytes(index, data); 50 | users_index[msg.sender].push(index); 51 | } 52 | 53 | function setBytes(bytes32 index, bytes calldata data) external payable payRef { 54 | setIndexBytes(index, data); 55 | } 56 | 57 | function setBytesMulti(bytes32[] calldata index, bytes[] calldata data) external payable payRef { 58 | require(index.length == data.length); 59 | for(uint256 i = 0; i < index.length; i++){ 60 | setIndexBytes(index[i], data[i]); 61 | users_index[msg.sender].push(index[i]); 62 | } 63 | } 64 | 65 | function updateUsersIndexWhereNeeded(bytes32[] calldata new_index) external payable payRef { 66 | for (uint i = 0; i < new_index.length; i++) { 67 | if (users_index[msg.sender][i] != new_index[i]) 68 | users_index[msg.sender][i] = new_index[i]; 69 | } 70 | } 71 | 72 | function updateUsersIndex(bytes32[] calldata new_index) external payable payRef { 73 | users_index[msg.sender] = new_index; 74 | } 75 | 76 | function clearBytesMulti(bytes32[] calldata indexes) external payable payRef{ 77 | for(uint256 i = 0; i < indexes.length; i++){ 78 | if(owner_index[indexes[i]] == msg.sender) 79 | clearIndexBytes(indexes[i]); 80 | } 81 | } 82 | 83 | function clearAll(uint256 pos, bytes32 index) external payable payRef requireOwner(index) { 84 | clearIndexBytes(index); 85 | deleteUserIndexAtPos(pos); 86 | } 87 | 88 | function appendSingleIndex(bytes32 index) external { 89 | users_index[msg.sender].push(index); 90 | } 91 | 92 | function updateSingleIndex(uint256 index, bytes32 new_index) external { 93 | users_index[msg.sender][index] = new_index; 94 | } 95 | 96 | function deleteSingleUserIndex(uint256 pos) external { 97 | deleteUserIndexAtPos(pos); 98 | } 99 | 100 | function ownershipTransferInit(bytes32 index, address addr) external { 101 | require(owner_index[index] == msg.sender); 102 | transfer_index[index] = addr; 103 | } 104 | 105 | function ownershipTransferAccept(bytes32 index) external { 106 | require(transfer_index[index] == msg.sender); 107 | owner_index[index] = msg.sender; 108 | } 109 | 110 | function clearOwnership(bytes32 index) external requireOwner(index) { 111 | owner_index[index] = 0x0000000000000000000000000000000000000000; 112 | } 113 | 114 | function getDataAtIndexArray(bytes32[] calldata index_array) external view returns (bytes[] memory){ 115 | bytes[] memory ret_string = new bytes[](index_array.length); 116 | for(uint256 i = 0; i < index_array.length; i++) 117 | ret_string[i] = indexed_space[index_array[i]]; 118 | return ret_string; 119 | } 120 | 121 | function getUserIndex(address addr) external view returns (bytes32[] memory){ 122 | return users_index[addr]; 123 | } 124 | 125 | function getUserBytes(address addr) external view returns (bytes[] memory, uint256, bytes32[] memory){ 126 | bytes[] memory ret_string = new bytes[](users_index[addr].length); 127 | for(uint256 i = 0; i < users_index[addr].length; i++) 128 | ret_string[i] = indexed_space[users_index[addr][i]]; 129 | return (ret_string, last_update[addr], users_index[addr]); 130 | } 131 | 132 | function getLastUpdate(address addr) external view returns (uint256) { 133 | return last_update[addr]; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /mod_contract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8; 3 | 4 | contract mod_contract { 5 | mapping(address => bool) private verified_contracts; 6 | address public auth_addr; 7 | uint256 public base_price; 8 | uint256 public tax_rate; 9 | mapping(address => bytes) private user_pk; 10 | mapping(address => bytes) private ecdh_pub; 11 | mapping(address => bytes) private ecdk_pk; 12 | mapping(bytes32 => address) private address_links; 13 | mapping(address => address) private refferal_addr; 14 | 15 | constructor(){ 16 | base_price = 1e18; 17 | tax_rate = 10; 18 | auth_addr = msg.sender; 19 | } 20 | 21 | receive() external payable {} 22 | 23 | modifier requireAuth(){ 24 | require(msg.sender == auth_addr); 25 | _; 26 | } 27 | 28 | function migrateInternalAuthAddr(address new_owner) external requireAuth{ 29 | auth_addr = new_owner; 30 | } 31 | 32 | function setVerifiedContractStatus(address c_addr, bool status) external requireAuth { 33 | verified_contracts[c_addr] = status; 34 | } 35 | 36 | function setBasePrice(uint256 new_bp) external requireAuth { 37 | base_price = new_bp; 38 | } 39 | 40 | function sendFunds(uint256 amount, address addr) external requireAuth { 41 | payable(addr).transfer(amount); 42 | } 43 | 44 | function setTaxRate(uint256 new_rate) external requireAuth { 45 | tax_rate = new_rate; 46 | } 47 | 48 | function externalCallAuth(address c_addr, bytes calldata data) external requireAuth { 49 | require(verified_contracts[c_addr]); 50 | (bool success, ) = c_addr.call(data); 51 | require(success); 52 | } 53 | 54 | function setString(bytes calldata new_string) internal { 55 | user_pk[msg.sender] = new_string; 56 | } 57 | 58 | function setReferrer(address ref) internal { 59 | if(ref != 0x0000000000000000000000000000000000000000) 60 | refferal_addr[msg.sender] = ref; 61 | } 62 | 63 | function initAccount(bytes calldata new_string, bytes32 link_hash, string calldata link_str, bytes calldata new_priv, bytes calldata new_pub, address new_ref) external payable { 64 | setReferrer(new_ref); 65 | createAddressLink(link_hash, link_str); 66 | setString(new_string); 67 | setPair(new_priv, new_pub); 68 | } 69 | 70 | function setPair(bytes calldata new_priv, bytes calldata new_pub) public { 71 | ecdk_pk[msg.sender] = new_priv; 72 | ecdh_pub[msg.sender] = new_pub; 73 | } 74 | 75 | function createAddressLink(bytes32 link_hash, string memory link_str) public payable { 76 | require(address_links[link_hash] == 0x0000000000000000000000000000000000000000, "link in use"); 77 | require(link_hash == keccak256(abi.encodePacked(link_str))); 78 | 79 | uint256 str_len = strlen(link_str); 80 | if(str_len >= 5) 81 | require(msg.value >= base_price/100); 82 | else if(str_len == 4) 83 | require(msg.value >= base_price/10); 84 | else if(str_len == 3) 85 | require(msg.value >= base_price); 86 | else if(str_len == 2) 87 | require(msg.value >= base_price*10); 88 | else if(str_len == 1) 89 | require(msg.value >= base_price*100); 90 | 91 | address_links[link_hash] = msg.sender; 92 | 93 | if(refferal_addr[msg.sender] != 0x0000000000000000000000000000000000000000) 94 | payable(refferal_addr[msg.sender]).transfer((msg.value / 100)*30); 95 | } 96 | 97 | function migrateAddressLink(bytes32 link_hash, address new_addr) external payable { 98 | require(msg.value >= base_price/100); 99 | require(address_links[link_hash] == msg.sender); 100 | address_links[link_hash] = new_addr; 101 | 102 | if(refferal_addr[msg.sender] != 0x0000000000000000000000000000000000000000) 103 | payable(refferal_addr[msg.sender]).transfer((msg.value / 100)*30); 104 | } 105 | 106 | function getReferrer(address addr) external view returns (address) { 107 | return refferal_addr[addr]; 108 | } 109 | 110 | function getPrivString(address addr) external view returns (bytes memory){ 111 | return ecdk_pk[addr]; 112 | } 113 | 114 | function getPubString(address addr) external view returns (bytes memory){ 115 | return ecdh_pub[addr]; 116 | } 117 | 118 | function getString(address addr) external view returns (bytes memory){ 119 | return user_pk[addr]; 120 | } 121 | 122 | function getAddressLink(bytes32 addr_link) external view returns (address){ 123 | return address_links[addr_link]; 124 | } 125 | 126 | function isVerifiedContract(address c_addr) external view returns (bool) { 127 | return verified_contracts[c_addr]; 128 | } 129 | 130 | function strlen(string memory link_str) internal pure returns (uint256) { 131 | uint256 len; 132 | uint256 i = 0; 133 | uint256 bytelength = bytes(link_str).length; 134 | 135 | for (len = 0; i < bytelength; len++) { 136 | bytes1 b = bytes(link_str)[i]; 137 | if (b < 0x80) 138 | i += 1; 139 | else if (b < 0xE0) 140 | i += 2; 141 | else if (b < 0xF0) 142 | i += 3; 143 | else if (b < 0xF8) 144 | i += 4; 145 | else if (b < 0xFC) 146 | i += 5; 147 | else 148 | i += 6; 149 | } 150 | return len; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /screenshots/alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/alert.png -------------------------------------------------------------------------------- /screenshots/cost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/cost.png -------------------------------------------------------------------------------- /screenshots/group61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/group61.png -------------------------------------------------------------------------------- /screenshots/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/hero.png -------------------------------------------------------------------------------- /screenshots/homescreen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/homescreen.jpg -------------------------------------------------------------------------------- /screenshots/note.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/note.webp -------------------------------------------------------------------------------- /screenshots/note2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/note2.png -------------------------------------------------------------------------------- /screenshots/updates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RockwellShah/bitnote/55077c800abee40926d6627578fe9b385a789d65/screenshots/updates.png -------------------------------------------------------------------------------- /sec_keys.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BUSL-1.1 2 | pragma solidity ^0.8; 3 | 4 | import "./authed_contract.sol"; 5 | 6 | contract sec_keys is authed_contract { 7 | mapping(bytes32 => bytes) private index_space; 8 | mapping(bytes32 => string) private name_space; 9 | 10 | constructor(address init_auth_contract) authed_contract(init_auth_contract){} 11 | 12 | function setDataAtIndex(bytes32 index, bytes calldata new_bytes, string calldata username) external requireOwnership(index) { 13 | index_space[index] = new_bytes; 14 | name_space[index] = username; 15 | } 16 | 17 | function getDataAtIndex(bytes32 index) external view returns (bytes memory, string memory){ 18 | return (index_space[index], name_space[index]); 19 | } 20 | } 21 | --------------------------------------------------------------------------------