nano25519
v1.0.1
Published
Public key derivation, transaction signing, and signature verification for Nano cryptocurrency using AssemblyScript.
Maintainers
Readme
nano25519
Block signing and validation for Nano cryptocurrency using WebAssembly.
nano25519 is an AssemblyScript implementation of select Ed25519 functions used by the Nano cryptocurrency. It is modified to hash using BLAKE2b instead of SHA-512 and can derive public keys from private keys, sign blocks, and verify block signatures. All processing takes place client-side and offline.
For more information about the public key derivation algorithm used by Nano, see https://docs.nano.org/integration-guides/the-basics/#account-public-key
For more information about the signature algorithm used by Nano, see https://docs.nano.org/protocol-design/signing-hashing-and-key-derivation/#signing-algorithm-ed25519
For more information about the block format defined for hashing and signing, see https://docs.nano.org/integration-guides/the-basics/#self-signed-blocks
Installation
npm i nano25519Browser
nano25519 can be used directly on a webpage with a script module:
<script type="module">
(async () => {
const nano25519 = await import("https://unpkg.com/nano25519@latest");
const { derive, sign, verify } = nano25519;
})();
</script>NodeJS
nano25519 can be imported into NodeJS projects:
import * as nano25519 from "nano25519";Sync and async modules can be imported separately depending on requirements.
import { derive, sign, verify } from "nano25519/sync";
import { deriveAsync, signAsync, verifyAsync } from "nano25519/async";Usage
Each function has a synchronous implementation which is preferable for speed.
If a non-blocking solution is required, asynchronous implementations are provided which use Web Workers in the browser or Worker threads in NodeJS.
Inputs can be passed as Uint8Array byte arrays (preferable) or strings. The output will return the same type as the input.
Derive
// `prv` is a 32-byte Uint8Array private key
const prv = new Uint8Array(32);
const pub = nano25519.derive(prvBytes);
// `pub` is a 32-byte Uint8Array public key for a Nano accountDerive (async)
// `prv` is a 64-character hex string private key
const prv = "0000000000000000000000000000000000000000000000000000000000000000";
const pub = await nano25519.deriveAsync(prv);
// `pub` is a 64-character hex string public key for a Nano accountSign
// `msg` is a 32-byte Uint8Array hash of a valid Nano transaction block
const msg = new Uint8Array(32);
// `prv` is a 32-byte Uint8Array private key
const prv = new Uint8Array(32);
// `pub` is a 32-byte Uint8Array public key derived from `prv`
const pub = nano25519.derive(prv);
// `sk` is a 64-byte Uint8Array secret key joining private and public keys
const sk = new Uint8Array([...prv, ...pub]);
const sig = nano25519.sign(msg, sk);
// `sig` is a 64-byte Uint8Array signature for the block hashSign (async)
// `msg` is a 64-char hex string hash of a valid Nano transaction block
const msg = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
// `prv` is a 64-char hex string private key
const prv = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
// `pub` is a 64-char hex string public key derived from `prv`
const pub = await nano25519.deriveAsync(prv);
// `sk` is a 128-char hex string secret key joining private and public keys
const sk = prv + pub;
const sig = await nano25519.signAsync(msg, sk);
// `sig` is a 128-char hex string signature for the block hashVerify
// `sig` is a 64-byte Uint8Array signature
const sig = new Uint8Array(64);
// `msg` is a 32-byte Uint8Array hash of a valid Nano transaction block
const msg = new Uint8Array(32);
// `pub` is a 32-byte Uint8Array public key for a Nano account
const pub = new Uint8Array(32);
const v = nano25519.verify(sig, msg, pub);
// `v` is a boolean 'true' if the same `prv` that derives `pub` was also used to create `sig` by signing `msg`, else 'false'Verify (async)
// `sig` is a 128-char hex string signature
const sig =
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
// `msg` is a 64-char hex string hash of a valid Nano transaction block
const msg = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
// `pub` is a 64-char hex string public key for a Nano account
const pub = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210";
const v = await nano25519.verifyAsync(sig, msg, pub);
// `v` is a boolean 'true' if the same `prv` that derives `pub` was also used to create `sig` by signing `msg`, else 'false'Notes
The tweetnacl-js implementation was originally selected as the basis for nano25519 due to its historical reliability and security. Over time, however, it became clear that tweetnacl was designed to optimize size and not speed. Soon after, libsodium became the reference from which functionality was ported.
For this project, the internal hash mechanism was altered to use BLAKE2b instead of SHA-512 so that it aligns with the Nano protocol. It has also been optimized to take advantage of SIMD parallelism using WebAssembly vector types.
Tests
A few basic tests are availabe in the source repository.
index.htmlis a web interface to test browser execution and compare performance with other browser-based implementations.test.mjsis a test for NodeJS to check result validity. It runs a derive-sign-verify sequence for public test vectors obtained from the python-ed25519-blake2b library.
Building
- Clone source
- Enter the directory
- Install dev dependencies
- Compile, minify, and bundle
git clone https://codecow.com/nano25519.git
cd nano25519
npm iReporting Bugs
Email: [email protected]
Acknowledgements
See AUTHORS.md
Licenses
GNU GPL version 3 or later https://gnu.org/licenses/gpl.html
libsodium is distributed under the ISC license and was referenced from the following commit hash: https://github.com/jedisct1/libsodium/tree/d24faf56214469b354b01c8ba36257e04737101e
tweetnacl-js is public domain under the Unlicense and was referenced from the following commit hash: https://github.com/dchest/tweetnacl-js/tree/e6141a20553498697e9e7d92fbc4517994caff52
Donations
Tips are always appreciated and can be sent to the following developer address:
nano_1zosoqs47yt47bnfg7sdf46kj7asn58b7uzm9ek95jw7ccatq37898u1zoso
