I am working on "ASTAR" parachain scene(TestNet: Shibuya).

I can sign message(unsigned-transaction) on offline environment and then broadcast signed-messaged(signed-transaction). When signing message, I used "signWith" method with keypair(keyring.addFromUri(mnemonic)).


I need to sign message(unsigned-transaction) with private-key created by below attached logic on offline environment.

But, I couldn't find out how to sign with that key.

    import { mnemonicGenerate, cryptoWaitReady, mnemonicToMiniSecret, ed25519PairFromSeed } from '@polkadot/util-crypto';
    import { hexToU8a, u8aToHex } from '@polkadot/util';
    import * as ed from '@noble/ed25519';  // npm install @noble/[email protected] (2.0 doesn't support import via 'require')
    const generatePrivateKeys = async () => {
        const mnemonic = mnemonicGenerate(); // Creates a valid mnemonic string using using [BIP39]
        console.log(`mnemonic : ${mnemonic}`);
        await cryptoWaitReady();
        const seed = mnemonicToMiniSecret(mnemonic);
        console.log(`seed : ${seed}`);
        const { publicKey, secretKey } = ed25519PairFromSeed(seed);
        const seedToImport = hexToU8a(u8aToHex(secretKey).slice(2,66));
        // console.log("initial seed :", u8aToHex(seedToImport));
        // Derive the Ed25519 key pair from the seed according to RFC-8032 (Section 5.1.5)
        const hash = await ed.utils.sha512(seedToImport)    
        let left = hash.slice(0,32)
        left[0] &= 248;
        left[31] &= 127;
        left[31] |= 64;
        const privateKeyToImport = modlLE(left);
        const publicKeyToImport = ed.Point.BASE.multiply(privateKeyToImport);
        console.log("private key :", privateKeyToImport.toString(16).padStart(64, '0'))
        console.log("public key  :", Buffer.from(publicKeyToImport.toRawBytes()).toString("hex"))
    function mod(a, b) {
        const res = a % b;
        return res >= BigInt(0) ? res : b + res;
    function bytesToNumberLE(uint8a) {
        if (!(uint8a instanceof Uint8Array))
            throw new Error('Expected Uint8Array');
        return BigInt('0x' + bytesToHex(Uint8Array.from(uint8a).reverse()));
    function modlLE(hash) {
        return mod(bytesToNumberLE(hash), ed.CURVE.l);
    const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'));
    function bytesToHex(uint8a) {
        if (!(uint8a instanceof Uint8Array))
            throw new Error('Uint8Array expected');
        let hex = '';
        for (let i = 0; i < uint8a.length; i++) {
            hex += hexes[uint8a[i]];
        return hex;
    generatePrivateKeys().catch(console.error).finally(() => process.exit());


Q1) Is it possible to sign a message with private key?

Q1-1) If so, can I get some reference contents or sample code?

Q1-2) If not, is it need to convert private key or another methods?

Q2) Where can I get some technical-information about cryptography on polkadot? Substate? or Parity?


  • What do you mean by sign with private key(Not secret key)? I want to know in what context you are referring private key and secret key. Commented Dec 1, 2023 at 5:44
  • private key is the result of "privateKeyToImport.toString(16).padStart(64, '0')" on the source code. And secret key is the variable of "const { publicKey, secretKey } = ed25519PairFromSeed(seed);"
    Commented Dec 1, 2023 at 6:28

1 Answer 1


Where can I get some technical-information about cryptography on polkadot? Substate? or Parity?

You can read the following resources to understand polkadot cryptography: https://wiki.polkadot.network/docs/learn-cryptography


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.