Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
150 lines (109 sloc) 4.94 KB

NIP 10 - Key Pair Generation and Address Format

    NIP: 10
    Layer: Core
    Title: Key Pair Generation and Address Format
    Author: gimre <g.imre@protonmail.com>
    Discussions-To: https://github.com/nemtech/NIP/issues/36
    Comments-URI: https://github.com/nemtech/NIP/issues/36
    Status: Active
    Type: Standards Track
    Created: 2020-02-06
    License: MIT

Introduction

Symbol is using Ed25519 signature scheme. The specification of the signature system from "High-speed high-security signatures" is not defining the hash function to be used.

First NEM network (nis1) is using pre-NIST version of Keccak as the hash function. Initial implementation of Symbol (catapult) was using two different hash functions:

  • pre-NIST Keccak - for backward compatibility of key pairs with NEM network
  • Sha3 - for new/private networks

For various reasons described later, this has been changed. All symbol networks will use Sha512 for key derivation.

For completeness, the document also describes address derivation, which also will be common for both types of networks.

Specification

Both public key derivation and signature generation follows specification from "High-speed high-security signatures".

The contents will not be replicated here, instead an example is given on how to generate public key from private using OpenSSL.

Key derivation using OpenSSL

Key passed to openssl will be in DER-encoded ASN.1 format, described briefly in RFC8410. So raw private key needs to be prefixed with some ASN.1 data.

xxd is a small tool present in most *nix distributions, used for converting between hex and binary.

The key in first example come straight from symbol test vectors repository:

$ export ASN1PREFIX="302e020100300506032b657004220420"
$ echo "${ASN1PREFIX}575dbb3062267eff57c970a336ebbc8fbcfe12c5bd3ed7bc11eb0481d7704ced" \
  | xxd -r -p \
  | openssl pkey -inform DER -text -noout

ED25519 Private-Key:
priv:
    57:5d:bb:30:62:26:7e:ff:57:c9:70:a3:36:eb:bc:
    8f:bc:fe:12:c5:bd:3e:d7:bc:11:eb:04:81:d7:70:
    4c:ed
pub:
    2e:83:41:40:fd:66:cf:87:b2:54:a6:93:a2:c7:86:
    2c:81:92:17:b6:76:d3:94:32:67:15:66:25:e8:16:
    ec:6f

Public key matches the first entry in 1.test-keys.json file inside test-vectors repository.

The key in the second example is a zero key.

$ echo "${ASN1PREFIX}0000000000000000000000000000000000000000000000000000000000000000" \
  | xxd -r -p \
  | openssl pkey -inform DER -text -noout

ED25519 Private-Key:
priv:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
    00:00
pub:
    3b:6a:27:bc:ce:b6:a4:2d:62:a3:a8:d0:2a:6f:0d:
    73:65:32:15:77:1d:e2:43:a6:3a:c0:48:a1:8b:59:
    da:29

Address format

Steps for generating addresses are described in Symbol Technical Reference

  1. Perform 256-bit Sha3 on the public key.
  2. Perform 160-bit RipeMD of hash resulting from step 1.
  3. Prepend network version byte to RipeMD hash.
  4. Perform 256-bit Sha3 on the result, take the first four bytes as a checksum.
  5. Concatenate output of step 3 and the checksum from step 4.
  6. Encode result using Base32.

The following example will convert public key obtained above to an address. 0x98 will be used as a network version byte.

$ export PUBKEY="2e:83:41:40:fd:66:cf:87:b2:54:a6:93:a2:c7:86:2c:81:92:17:b6:76:d3:94:32:67:15:66:25:e8:16:ec:6f"
$ PART1=$(echo "${PUBKEY}" \
  | sed 's/://g' \
  | xxd -r -p \
  | openssl sha3-256 -binary \
  | openssl ripemd -r 
  | cut -d' ' -f1)
$ PART2=$(echo "98${PART1}")
$ CHECKSUM=$(echo "${PART2}" \
  | xxd -r -p \
  | openssl sha3-256 -r \
  | cut -b 1-8)
$ HEXADDRESS="${PART2}${CHECKSUM}"
$ echo "${HEXADDRESS}" | xxd -r -p | base32
TATNE7Q5BITMUTRRN6IB4I7FLSDRDWZA37JGO5UW

Output matches the first entry in 1.test-address.json file inside test-vectors repository.

Design Decisions

The main rationale behind this change is the upcoming introduction of TLS inside the server. It also turned out, that key compatibility is it unwanted by exchanges, due to security concerns.

These changes also should make interoperability much easier.

Implementation

The server part of the changes is already available inside catapult-server repository.

Changes will be released as part of 0.9.3.1 build.

Backwards compatibility

As stated above, the changes are not backward compatible and will require new nemesis block in the testnet.

Alternatives

Before introducing this breaking change, other alternatives were considered, but they are related to TLS introduction and are outside the scope of this document.

References

History

Date Version
Feb 06 2020 1.0
You can’t perform that action at this time.