Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Module 0x1::ed25519

Contains functions for:

  1. Ed25519 digital signatures: i.e., EdDSA signatures over Edwards25519 curves with co-factor 8
use 0x1::bcs;
use 0x1::error;
use 0x1::hash;
use 0x1::option;
use 0x1::type_info;

Struct SignedMessage

A BCS-serializable message, which one can verify signatures on via signature_verify_strict_t

struct SignedMessage<MessageType> has drop
Fields
type_info: type_info::TypeInfo
inner: MessageType

Struct UnvalidatedPublicKey

An unvalidated Ed25519 public key: not necessarily an elliptic curve point, just a sequence of 32 bytes

struct UnvalidatedPublicKey has copy, drop, store
Fields
bytes: vector<u8>

Struct ValidatedPublicKey

A validated Ed25519 public key: not necessarily a prime-order point, could be mixed-order, but will never be a small-order point.

For now, this struct is not used in any verification functions, but it might be in the future.

struct ValidatedPublicKey has copy, drop, store
Fields
bytes: vector<u8>

Struct Signature

A purported Ed25519 signature that can be verified via signature_verify_strict or signature_verify_strict_t.

struct Signature has copy, drop, store
Fields
bytes: vector<u8>

Constants

The size of a serialized public key, in bytes.

const PUBLIC_KEY_NUM_BYTES: u64 = 32;

Wrong number of bytes were given as input when deserializing an Ed25519 public key.

const E_WRONG_PUBKEY_SIZE: u64 = 1;

Wrong number of bytes were given as input when deserializing an Ed25519 signature.

const E_WRONG_SIGNATURE_SIZE: u64 = 2;

The size of a serialized signature, in bytes.

const SIGNATURE_NUM_BYTES: u64 = 64;

The identifier of the Ed25519 signature scheme, which is used when deriving Aptos authentication keys by hashing it together with an Ed25519 public key.

const SIGNATURE_SCHEME_ID: u8 = 0;

Function new_unvalidated_public_key_from_bytes

Parses the input 32 bytes as an unvalidated Ed25519 public key.

public fun new_unvalidated_public_key_from_bytes(bytes: vector<u8>): ed25519::UnvalidatedPublicKey
Implementation
public fun new_unvalidated_public_key_from_bytes(bytes: vector<u8>): UnvalidatedPublicKey {
    assert!(bytes.length() == PUBLIC_KEY_NUM_BYTES, std::error::invalid_argument(E_WRONG_PUBKEY_SIZE));
    UnvalidatedPublicKey { bytes }
}

Function new_validated_public_key_from_bytes

Parses the input 32 bytes as a validated Ed25519 public key.

public fun new_validated_public_key_from_bytes(bytes: vector<u8>): option::Option<ed25519::ValidatedPublicKey>
Implementation
public fun new_validated_public_key_from_bytes(bytes: vector<u8>): Option<ValidatedPublicKey> {
    if (public_key_validate_internal(bytes)) {
        option::some(ValidatedPublicKey {
            bytes
        })
    } else {
        option::none<ValidatedPublicKey>()
    }
}

Function new_signature_from_bytes

Parses the input 64 bytes as a purported Ed25519 signature.

public fun new_signature_from_bytes(bytes: vector<u8>): ed25519::Signature
Implementation
public fun new_signature_from_bytes(bytes: vector<u8>): Signature {
    assert!(bytes.length() == SIGNATURE_NUM_BYTES, std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE));
    Signature { bytes }
}

Function public_key_to_unvalidated

Converts a ValidatedPublicKey to an UnvalidatedPublicKey, which can be used in the strict verification APIs.

public fun public_key_to_unvalidated(pk: &ed25519::ValidatedPublicKey): ed25519::UnvalidatedPublicKey
Implementation
public fun public_key_to_unvalidated(pk: &ValidatedPublicKey): UnvalidatedPublicKey {
    UnvalidatedPublicKey {
        bytes: pk.bytes
    }
}

Function public_key_into_unvalidated

Moves a ValidatedPublicKey into an UnvalidatedPublicKey, which can be used in the strict verification APIs.

public fun public_key_into_unvalidated(pk: ed25519::ValidatedPublicKey): ed25519::UnvalidatedPublicKey
Implementation
public fun public_key_into_unvalidated(pk: ValidatedPublicKey): UnvalidatedPublicKey {
    UnvalidatedPublicKey {
        bytes: pk.bytes
    }
}

Function unvalidated_public_key_to_bytes

Serializes an UnvalidatedPublicKey struct to 32-bytes.

public fun unvalidated_public_key_to_bytes(pk: &ed25519::UnvalidatedPublicKey): vector<u8>
Implementation
public fun unvalidated_public_key_to_bytes(pk: &UnvalidatedPublicKey): vector<u8> {
    pk.bytes
}

Function validated_public_key_to_bytes

Serializes an ValidatedPublicKey struct to 32-bytes.

public fun validated_public_key_to_bytes(pk: &ed25519::ValidatedPublicKey): vector<u8>
Implementation
public fun validated_public_key_to_bytes(pk: &ValidatedPublicKey): vector<u8> {
    pk.bytes
}

Function signature_to_bytes

Serializes a Signature struct to 64-bytes.

public fun signature_to_bytes(sig: &ed25519::Signature): vector<u8>
Implementation
public fun signature_to_bytes(sig: &Signature): vector<u8> {
    sig.bytes
}

Function public_key_validate

Takes in an unvalidated public key and attempts to validate it. Returns Some(ValidatedPublicKey) if successful and None otherwise.

public fun public_key_validate(pk: &ed25519::UnvalidatedPublicKey): option::Option<ed25519::ValidatedPublicKey>
Implementation
public fun public_key_validate(pk: &UnvalidatedPublicKey): Option<ValidatedPublicKey> {
    new_validated_public_key_from_bytes(pk.bytes)
}

Function signature_verify_strict

Verifies a purported Ed25519 signature under an unvalidated public_key on the specified message. This call will validate the public key by checking it is NOT in the small subgroup.

public fun signature_verify_strict(signature: &ed25519::Signature, public_key: &ed25519::UnvalidatedPublicKey, message: vector<u8>): bool
Implementation
public fun signature_verify_strict(
    signature: &Signature,
    public_key: &UnvalidatedPublicKey,
    message: vector<u8>
): bool {
    signature_verify_strict_internal(signature.bytes, public_key.bytes, message)
}

Function signature_verify_strict_t

This function is used to verify a signature on any BCS-serializable type T. For now, it is used to verify the proof of private key ownership when rotating authentication keys.

public fun signature_verify_strict_t<T: drop>(signature: &ed25519::Signature, public_key: &ed25519::UnvalidatedPublicKey, data: T): bool
Implementation
public fun signature_verify_strict_t<T: drop>(signature: &Signature, public_key: &UnvalidatedPublicKey, data: T): bool {
    let encoded = SignedMessage {
        type_info: type_info::type_of<T>(),
        inner: data,
    };

    signature_verify_strict_internal(signature.bytes, public_key.bytes, bcs::to_bytes(&encoded))
}

Function new_signed_message

Helper method to construct a SignedMessage struct.

public fun new_signed_message<T: drop>(data: T): ed25519::SignedMessage<T>
Implementation
public fun new_signed_message<T: drop>(data: T): SignedMessage<T> {
    SignedMessage {
        type_info: type_info::type_of<T>(),
        inner: data,
    }
}

Function unvalidated_public_key_to_authentication_key

Derives the Aptos-specific authentication key of the given Ed25519 public key.

public fun unvalidated_public_key_to_authentication_key(pk: &ed25519::UnvalidatedPublicKey): vector<u8>
Implementation
public fun unvalidated_public_key_to_authentication_key(pk: &UnvalidatedPublicKey): vector<u8> {
    public_key_bytes_to_authentication_key(pk.bytes)
}

Function validated_public_key_to_authentication_key

Derives the Aptos-specific authentication key of the given Ed25519 public key.

public fun validated_public_key_to_authentication_key(pk: &ed25519::ValidatedPublicKey): vector<u8>
Implementation
public fun validated_public_key_to_authentication_key(pk: &ValidatedPublicKey): vector<u8> {
    public_key_bytes_to_authentication_key(pk.bytes)
}

Function public_key_bytes_to_authentication_key

Derives the Aptos-specific authentication key of the given Ed25519 public key.

fun public_key_bytes_to_authentication_key(pk_bytes: vector<u8>): vector<u8>
Implementation
fun public_key_bytes_to_authentication_key(pk_bytes: vector<u8>): vector<u8> {
    pk_bytes.push_back(SIGNATURE_SCHEME_ID);
    std::hash::sha3_256(pk_bytes)
}

Function public_key_validate_internal

Return true if the bytes in public_key can be parsed as a valid Ed25519 public key: i.e., it passes points-on-curve and not-in-small-subgroup checks. Returns false otherwise.

fun public_key_validate_internal(bytes: vector<u8>): bool
Implementation
native fun public_key_validate_internal(bytes: vector<u8>): bool;

Function signature_verify_strict_internal

Return true if the Ed25519 signature on message verifies against the Ed25519 public_key. Returns false if either:

  • signature or public key are of wrong sizes
  • public_key does not pass points-on-curve or not-in-small-subgroup checks,
  • signature does not pass points-on-curve or not-in-small-subgroup checks,
  • the signature on message does not verify.
fun signature_verify_strict_internal(signature: vector<u8>, public_key: vector<u8>, message: vector<u8>): bool
Implementation
native fun signature_verify_strict_internal(
    signature: vector<u8>,
    public_key: vector<u8>,
    message: vector<u8>
): bool;

Specification

Function new_unvalidated_public_key_from_bytes

public fun new_unvalidated_public_key_from_bytes(bytes: vector<u8>): ed25519::UnvalidatedPublicKey
include NewUnvalidatedPublicKeyFromBytesAbortsIf;
ensures result == UnvalidatedPublicKey { bytes };

schema NewUnvalidatedPublicKeyFromBytesAbortsIf {
    bytes: vector<u8>;
    aborts_if len(bytes) != PUBLIC_KEY_NUM_BYTES;
}

Function new_validated_public_key_from_bytes

public fun new_validated_public_key_from_bytes(bytes: vector<u8>): option::Option<ed25519::ValidatedPublicKey>
aborts_if false;
let cond = spec_public_key_validate_internal(bytes);
ensures cond ==> result == option::spec_some(ValidatedPublicKey{bytes});
ensures !cond ==> result == option::spec_none<ValidatedPublicKey>();

Function new_signature_from_bytes

public fun new_signature_from_bytes(bytes: vector<u8>): ed25519::Signature
include NewSignatureFromBytesAbortsIf;
ensures result == Signature { bytes };

schema NewSignatureFromBytesAbortsIf {
    bytes: vector<u8>;
    aborts_if len(bytes) != SIGNATURE_NUM_BYTES;
}

Function public_key_validate

public fun public_key_validate(pk: &ed25519::UnvalidatedPublicKey): option::Option<ed25519::ValidatedPublicKey>
pragma opaque;
aborts_if false;
let cond = spec_public_key_validate_internal(pk.bytes);
ensures cond ==> result == option::spec_some(ValidatedPublicKey { bytes: pk.bytes });
ensures !cond ==> result == option::spec_none<ValidatedPublicKey>();

Function signature_verify_strict

public fun signature_verify_strict(signature: &ed25519::Signature, public_key: &ed25519::UnvalidatedPublicKey, message: vector<u8>): bool
pragma opaque;
aborts_if false;
ensures result == spec_signature_verify_strict_internal(signature.bytes, public_key.bytes, message);

Function signature_verify_strict_t

public fun signature_verify_strict_t<T: drop>(signature: &ed25519::Signature, public_key: &ed25519::UnvalidatedPublicKey, data: T): bool
pragma opaque;
aborts_if !type_info::spec_is_struct<T>();
ensures result == spec_signature_verify_strict_t(signature, public_key, data);

Function new_signed_message

public fun new_signed_message<T: drop>(data: T): ed25519::SignedMessage<T>
pragma opaque;
aborts_if !type_info::spec_is_struct<T>();
ensures result == SignedMessage<T> { type_info: type_info::type_of<T>(), inner: data };

Function unvalidated_public_key_to_authentication_key

public fun unvalidated_public_key_to_authentication_key(pk: &ed25519::UnvalidatedPublicKey): vector<u8>
pragma opaque;
aborts_if false;
ensures result == spec_public_key_bytes_to_authentication_key(pk.bytes);

Function validated_public_key_to_authentication_key

public fun validated_public_key_to_authentication_key(pk: &ed25519::ValidatedPublicKey): vector<u8>
pragma opaque;
aborts_if false;
ensures result == spec_public_key_bytes_to_authentication_key(pk.bytes);

Function public_key_bytes_to_authentication_key

fun public_key_bytes_to_authentication_key(pk_bytes: vector<u8>): vector<u8>
pragma opaque;
aborts_if false;
ensures [abstract] result == spec_public_key_bytes_to_authentication_key(pk_bytes);

Function public_key_validate_internal

fun public_key_validate_internal(bytes: vector<u8>): bool
pragma opaque;
aborts_if false;
ensures result == spec_public_key_validate_internal(bytes);

Function signature_verify_strict_internal

fun signature_verify_strict_internal(signature: vector<u8>, public_key: vector<u8>, message: vector<u8>): bool
pragma opaque;
aborts_if false;
ensures result == spec_signature_verify_strict_internal(signature, public_key, message);

Helper functions

fun spec_signature_verify_strict_internal(
   signature: vector<u8>,
   public_key: vector<u8>,
   message: vector<u8>
): bool;

fun spec_public_key_validate_internal(bytes: vector<u8>): bool;

fun spec_public_key_bytes_to_authentication_key(pk_bytes: vector<u8>): vector<u8>;

fun spec_signature_verify_strict_t<T>(signature: Signature, public_key: UnvalidatedPublicKey, data: T): bool {
   let encoded = SignedMessage<T> {
       type_info: type_info::type_of<T>(),
       inner: data,
   };
   let message = bcs::serialize(encoded);
   spec_signature_verify_strict_internal(signature.bytes, public_key.bytes, message)
}