waves_logo Docs
  • Why Waves
    Why Waves
  • Waves Basics
    Waves Basics
  • Account
    • Creating Account
      Creating Account
    • Address
      Address
    • Account Balance
      Account Balance
    • Account Data Storage
      Account Data Storage
    • Alias
      Alias
    • dApp and Smart Account
      dApp and Smart Account
    Account
  • Token (Asset)
    • Non-Fungible Token
      Non-Fungible Token
    • Smart Asset
      Smart Asset
    • Token ID
      Token ID
    • WAVES
      WAVES
    Token (Asset)
  • Transaction
    • Transaction Fee
      • Sponsored Fee
        Sponsored Fee
      Transaction Fee
    • Signature and Proofs
      Signature and Proofs
    • Transaction Types
      • Burn Transaction
        Burn Transaction
      • Create Alias Transaction
        Create Alias Transaction
      • Data Transaction
        Data Transaction
      • Exchange Transaction
        • Order
          Order
        Exchange Transaction
      • Genesis Transaction
        Genesis Transaction
      • Invoke Script Transaction
        Invoke Script Transaction
      • Issue Transaction
        Issue Transaction
      • Lease Cancel Transaction
        Lease Cancel Transaction
      • Lease Transaction
        Lease Transaction
      • Mass Transfer Transaction
        Mass Transfer Transaction
      • Reissue Transaction
        Reissue Transaction
      • Set Asset Script Transaction
        Set Asset Script Transaction
      • Set Script Transaction
        Set Script Transaction
      • Sponsor Fee Transaction
        Sponsor Fee Transaction
      • Transfer Transaction
        Transfer Transaction
      • Update Asset Info Transaction
        Update Asset Info Transaction
      • Ethereum-like Transaction
        Ethereum-like Transaction
      Transaction Types
    • Transaction Validation
      Transaction Validation
    Transaction
  • Block
    • Transactions Root Hash
      Transactions Root Hash
    • Genesis Block
      Genesis Block
    Block
  • Node
    • Leasing
      Leasing
    • Generator’s Income
      Generator’s Income
    • Monetary Policy
      Monetary Policy
    Node
  • Mainnet, Testnet, Stagenet
    Mainnet, Testnet, Stagenet
  • Unit Zero
    Unit Zero
  • Oracle
    Oracle
  • Protocols & Data formats
    • Cryptographic Practical Details
      Cryptographic Practical Details
    • Leased Proof of Stake
      Leased Proof of Stake
    • Waves-NG Solution
      Waves-NG Solution
    • Waves-NG Protocol
      Waves-NG Protocol
    • Waves 1.5
      Waves 1.5
    • Blockchain Data Types
      Blockchain Data Types
    • Binary Format
      • Address Binary Format
        Address Binary Format
      • Alias Binary Format
        Alias Binary Format
      • Block Binary Format
        Block Binary Format
      • Network Message Binary Format
        • Block Message Binary Format
          Block Message Binary Format
        • Checkpoint Message Binary Format
          Checkpoint Message Binary Format
        • Get Block Message Binary Format
          Get Block Message Binary Format
        • Get Peers Message Binary Format
          Get Peers Message Binary Format
        • Get Signatures Message Binary Format
          Get Signatures Message Binary Format
        • Handshake Message Binary Format
          Handshake Message Binary Format
        • Peers Message Binary Format
          Peers Message Binary Format
        • Score Message Binary Format
          Score Message Binary Format
        • Signatures Message Binary Format
          Signatures Message Binary Format
        • Transaction Message Message Binary Format
          Transaction Message Message Binary Format
        Network Message Binary Format
      • Order Binary Format
        Order Binary Format
      • Transaction Binary Format
        • Burn Transaction Binary Format
          Burn Transaction Binary Format
        • Create Alias Transaction Binary Format
          Create Alias Transaction Binary Format
        • Data Transaction Binary Format
          Data Transaction Binary Format
        • Exchange Transaction Binary Format
          Exchange Transaction Binary Format
        • Genesis Transaction Binary Format
          Genesis Transaction Binary Format
        • Invoke Script Transaction Binary Format
          Invoke Script Transaction Binary Format
        • Issue Transaction Binary Format
          Issue Transaction Binary Format
        • Lease Cancel Transaction Binary Format
          Lease Cancel Transaction Binary Format
        • Lease Transaction Binary Format
          Lease Transaction Binary Format
        • Mass Transfer Transaction Binary Format
          Mass Transfer Transaction Binary Format
        • Reissue Transaction Binary Format
          Reissue Transaction Binary Format
        • Set Asset Script Transaction Binary Format
          Set Asset Script Transaction Binary Format
        • Set Script Transaction Binary Format
          Set Script Transaction Binary Format
        • Sponsor Fee Transaction Binary Format
          Sponsor Fee Transaction Binary Format
        • Transfer Transaction Binary Format
          Transfer Transaction Binary Format
        • Update Asset Info Transaction Binary Format
          Update Asset Info Transaction Binary Format
        • Ethereum-like Transaction Binary Format
          Ethereum-like Transaction Binary Format
        Transaction Binary Format
      • Transaction Proof Binary Format
        Transaction Proof Binary Format
      Binary Format
    • Validation Rules
      Validation Rules
    Protocols & Data formats
  • Glossary
    Glossary
      • English
      • Русский
      On this page
        • Description
        • Bytes encoding Base58
        • Creating a private key from a seed
        • Creating address from public key
        • Signing
        • Calculating Transaction Id
      waves_logo Docs

          # Cryptographic practical details

          # Description

          This section describes all the details of cryptographic algorithms which are used to:

          1. Create private and public keys from seed.
          2. Create addresses from public key.
          3. Create blocks and transactions signing.

          We use:

          1. Blake2b256 and Keccak256 algorithms (in the form of hash chain) to create a cryptographic hashes.
          2. Curve25519 (ED25519 with X25519 keys) to create and verify signatures.
          3. Base58 to create the string form of bytes.

          Note: We use KECCAK which differs slightly than that assigned as the SHA-3 (FIPS-202).

          # Bytes encoding Base58

          All arrays of bytes in the project are encoded by Base58 algorithm with Bitcoin alphabet to make it ease human readable (text readability).

          # Example

          The string teststring is coded into the bytes [5, 83, 9, -20, 82, -65, 120, -11]. The bytes [1, 2, 3, 4, 5] are coded into the string 7bWpTW.

          # Creating a private key from a seed

          A seed string is a representation of entropy, from which you can re-create deterministically all the private keys for one wallet. It should be long enough so that the probability of selection is an unrealistic negligible.

          In fact, seed should be an array of bytes but for ease of memorization lite wallet uses Brainwallet , to ensure that the seed is made up of words and easy to write down or remember. The application takes the UTF-8 bytes of the string and uses them to create keys and addresses.

          For example, seed string manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add after reading this string as UTF-8 bytes and encoding them to Base58, the string will be coded as:

          xrv7ffrv2A9g5pKSxt7gHGrPYJgRnsEMDyc4G7srbia6PhXYLDKVsDxnqsEqhAVbbko7N1tDyaSrWCZBoMyvdwaFNjWNPjKdcoZTKbKr2Vw9vu53Uf4dYpyWCyvfPbRskHfgt9q
          

          A seed string is involved with the creation of private keys. To create private key using the official web wallet or the node, to 4 bytes of int 'nonce' field (big-endian representation), which initially has a value of 0 and increases every time you create the new address, should be prepended to seed bytes. Then we use this array of bytes for calculate hash keccak256(blake2b256(bytes)). This resulting array of bytes we call account seed, from it you can definitely generate one private and public key pair. Then this bytes hash passed in the method of creating a pair of public and private key of Curve25519 algorithm.

          Waves uses Curve25519-ED25519 signature with X25519 keys (Montgomery form), but most of embedded cryptography devices and libraries don't support X25519 keys.

          There're libraries with conversion functions from:

          • ED25519 keys to X25519 (Curve25519) crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) for public key.
          • Crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk) for private key.

          For example, I use the ED25519 keys and the signature inside the Ledger application, then it need to convert the keys from the device to X25519 format using that function on the client sideand create the waves address from X25519 public key. There're an example of convertion libsodium ED25519 keys and signature to Curve25519 .

          NOTE: Not all random 32 bytes can be used as private keys (but any bytes of any size can be a seed). The signature scheme for the ED25519 introduces restrictions on the keys, so create the keys only through the methods of the Curve25519 libraries and be sure to make a test of the ability to sign data with a private key and then check it with a public key, however obvious this test might seem.

          There are valid Curve25519 realizations for different languages:

          • Java
          • C
          • Python
          • JS

          Also some Curve25519 libraries (as the one used in our project) have the Sha256 hashing integrated, some not (such as most of c/c++/python libraries), so you may need to apply it manually. Note that private key is clamped, so not any random 32 bytes can be a valid private key.

          # Example

          Brainwallet seed string

          manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add
          

          As UTF-8 bytes encoded

          xrv7ffrv2A9g5pKSxt7gHGrPYJgRnsEMDyc4G7srbia6PhXYLDKVsDxnqsEqhAVbbko7N1tDyaSrWCZBoMyvdwaFNjWNPjKdcoZTKbKr2Vw9vu53Uf4dYpyWCyvfPbRskHfgt9q
          

          Account seed bytes with nonce 0 before apply hash function in Base58

          1111xrv7ffrv2A9g5pKSxt7gHGrPYJgRnsEMDyc4G7srbia6PhXYLDKVsDxnqsEqhAVbbko7N1tDyaSrWCZBoMyvdwaFNjWNPjKdcoZTKbKr2Vw9vu53Uf4dYpyWCyvfPbRskHfgt9q
          

          blake2b256(account seed bytes)

          6sKMMHVLyCQN7Juih2e9tbSmeE5Hu7L8XtBRgowJQvU7
          

          Account seed ( keccak256(blake2b256(account seed bytes)) )

          H4do9ZcPUASvtFJHvESapnxfmQ8tjBXMU7NtUARk9Jrf
          

          Account seed after Sha256 hashing (optional, if your library does not do it yourself)

          49mgaSSVQw6tDoZrHSr9rFySgHHXwgQbCRwFssboVLWX
          

          Created private key

          3kMEhU5z3v8bmer1ERFUUhW58Dtuhyo9hE5vrhjqAWYT
          

          Created public key

          HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8
          

          # Creating address from public key

          Our network address obtained from the public key depends on the byte chainId ('T' for Testnet, 'W' for Mainnet, 'S' for Stagenet), so different networks obtained a different address for a single seed (and hence public keys). Creating a byte addresses described in more detail here.

          Example

          For public key

          HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8
          

          in mainnet network (chainId 'W') will be created this address

          3PPbMwqLtwBGcJrTA5whqJfY95GqnNnFMDX
          

          # Signing

          Curve25519 is used for all the signatures in the project.

          The process is as follows: create the special bytes for signing for transaction or block, you can find it here, then create a signature using these bytes and the private key bytes.

          For the validation of signature is enough signature bytes, signed object bytes and the public key.

          Do not forget that there are many valid (not unique!) signatures for a one array of bytes (block or transaction). Also you should not assume that the id of block or transaction is unique. The collision can occur one day! They have already taken place for some weak keys.

          # Example

          Transaction data:

          Field Value
          Sender address (not used, just for information) 3N9Q2sdkkhAnbR4XCveuRaSMLiVtvebZ3wp
          Private key (used for signing, not in tx data) 7VLYNhmuvAo5Us4mNGxWpzhMSdSSdEbEPFUDKSnA6eBv
          Public key EENPV1mRhUD9gSKbcWt84cqnfSGQP5LkCu5gMBfAanYH
          Recipient address 3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8
          Asset id BG39cCNUFWPQYeyLnu7tjKHaiUGRxYwJjvntt9gdDPxG
          Amount 1
          Fee 1
          Fee asset id BG39cCNUFWPQYeyLnu7tjKHaiUGRxYwJjvntt9gdDPxG
          Timestamp 1479287120875
          Attachment (as byte array) [1, 2, 3, 4]

          Bytes:

          # Field name Type Position Length Value Base58 bytes value
          1 Transaction type (0x04) Byte 0 1 4 5
          2 Sender's public key Bytes 1 32 ... EENPV1mRhUD9gSKbcWt84cqnfSGQP5LkCu5gMBfAanYH
          3 Amount's asset flag (0-Waves, 1-Asset) Byte 33 1 1 2
          4 Amount's asset ID (*if used) Bytes 34 0 (32*) ... BG39cCNUFWPQYeyLnu7tjKHaiUGRxYwJjvntt9gdDPxG
          5 Fee's asset flag (0-Waves, 1-Asset) Byte 34 (66*) 1 1 2
          6 Fee's asset ID (**if used) Bytes 35 (67*) 0 (32**) ... BG39cCNUFWPQYeyLnu7tjKHaiUGRxYwJjvntt9gdDPxG
          7 Timestamp Long 35 (67_) (99*_) 8 1479287120875 11frnYASv
          8 Amount Long 43 (75_) (107*_) 8 1 11111112
          9 Fee Long 51 (83_) (115*_) 8 1 11111112
          10 Recipient's address Bytes 59 (91_) (123*_) 26 ... 3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8
          11 Attachment's length (N) Short 85 (117_) (149*_) 2 4 15
          12 Attachment's bytes Bytes 87 (119_) (151*_) N [1,2,3,4] 2VfUX

          Total data bytes for sign:

          Ht7FtLJBrnukwWtywum4o1PbQSNyDWMgb4nXR5ZkV78krj9qVt17jz74XYSrKSTQe6wXuPdt3aCvmnF5hfjhnd1gyij36hN1zSDaiDg3TFi7c7RbXTHDDUbRgGajXci8PJB3iJM1tZvh8AL5wD4o4DCo1VJoKk2PUWX3cUydB7brxWGUxC6mPxKMdXefXwHeB4khwugbvcsPgk8F6YB
          

          Signature of transaction data bytes (one of an infinite number of valid signatures):

          2mQvQFLQYJBe9ezj7YnAQFq7k9MxZstkrbcSKpLzv7vTxUfnbvWMUyyhJAc1u3vhkLqzQphKDecHcutUrhrHt22D
          

          Total transaction bytes with signature:

          6zY3LYmrh981Qbzj7SRLQ2FP9EmXFpUTX9cA7bD5b7VSGmtoWxfpCrP4y5NPGou7XDYHx5oASPsUzB92aj3623SUpvc1xaaPjfLn6dCPVEa6SPjTbwvmDwMT8UVoAfdMwb7t4okLcURcZCFugf2Wc9tBGbVu7mgznLGLxooYiJmRQSeAACN8jYZVnUuXv4V7jrDJVXTFNCz1mYevnpA5RXAoehPRXKiBPJLnvVmV2Wae2TCNvweHGgknioZU6ZaixSCxM1YzY24Prv9qThszohojaWq4cRuRHwMAA5VUBvUs
          

          # Calculating Transaction Id

          Transaction Id is not stored in the transaction bytes and for most of transactions (except Payment) it can be easily calculated from the special bytes for signing using blake2b256(bytes_for_signing). For Payment transaction Id is just the signature of this transaction.

          Protocols & Data formats
          Leased Proof of Stake
          Protocols & Data formats
          Leased Proof of Stake