Ed25519 signatures¶
This module provides the protocol layer for Ed25519 as specified by RFC 8032.
The underlying curve group is the native twisted Edwards group provided by
sage.schemes.elliptic_curves.ell_edwards. Keeping the two layers
separate is important: a generic twisted Edwards curve has an equation and a
group law, while Ed25519 additionally fixes the field, parameters, base point,
cofactor, hash function, scalar pruning, and byte encoding.
The public functions implement deterministic Ed25519, Ed25519ctx, and Ed25519ph signing and verification using the 32-byte private-key seed format from RFC 8032. Ed25519ctx separates signatures by a caller-supplied context; Ed25519ph hashes the message before signing and can also use a context. The three variants have different signature domains and are not interchangeable:
sage: seed = bytes.fromhex("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
sage: public_key = ed25519_public_key(seed)
sage: public_key.hex()
'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
sage: signature = ed25519_sign(seed, b"")
sage: signature.hex()
'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
sage: ed25519_verify(public_key, b"", signature)
True
>>> from sage.all import *
>>> seed = bytes.fromhex("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
>>> public_key = ed25519_public_key(seed)
>>> public_key.hex()
'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
>>> signature = ed25519_sign(seed, b"")
>>> signature.hex()
'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
>>> ed25519_verify(public_key, b"", signature)
True
seed = bytes.fromhex("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
public_key = ed25519_public_key(seed)
public_key.hex()
signature = ed25519_sign(seed, b"")
signature.hex()
ed25519_verify(public_key, b"", signature)
For an object-oriented interface that bundles the variant and context into a
single scheme object with the secret_key / public_key / sign /
verify operation shape of the digital-signature framework proposed in
Issue #42856, use Ed25519SignatureScheme.
The curve constructor and base point are cached, so ordinary Sage additive group operations can be used directly without a second hand-written scalar multiplication implementation:
sage: C = Ed25519()
sage: B = Ed25519BasePoint()
sage: C(B) == B
True
sage: ed25519_decode(ed25519_encode(B)) == B
True
>>> from sage.all import *
>>> C = Ed25519()
>>> B = Ed25519BasePoint()
>>> C(B) == B
True
>>> ed25519_decode(ed25519_encode(B)) == B
True
C = Ed25519() B = Ed25519BasePoint() C(B) == B ed25519_decode(ed25519_encode(B)) == B
This module intentionally does not provide X25519 or an interchangeable private-key object. X25519 is a different protocol using the Montgomery form and Ed25519’s signing key is a seed, not the already-pruned scalar.
REFERENCES:
AUTHORS:
SageMath developers (2026): initial Ed25519 protocol support
- sage.crypto.ed25519.Ed25519()[source]¶
Return the standard Ed25519 twisted Edwards curve.
The returned parent is the curve
\[-x^2 + y^2 = 1 + d x^2 y^2, \qquad d = -121665/121666\]over
GF(2^255 - 19). The protocol-specific encoding and signing functions areed25519_encode(),ed25519_decode(),ed25519_sign(), anded25519_verify().EXAMPLES:
sage: C = Ed25519() sage: C.base_ring().order() == ED25519_FIELD_SIZE True sage: C.a() == -1 True sage: C.d() == C.base_ring()(-121665) / C.base_ring()(121666) True
>>> from sage.all import * >>> C = Ed25519() >>> C.base_ring().order() == ED25519_FIELD_SIZE True >>> C.a() == -Integer(1) True >>> C.d() == C.base_ring()(-Integer(121665)) / C.base_ring()(Integer(121666)) True
C = Ed25519() C.base_ring().order() == ED25519_FIELD_SIZE C.a() == -1 C.d() == C.base_ring()(-121665) / C.base_ring()(121666)
- sage.crypto.ed25519.Ed25519BasePoint()[source]¶
Return the standard Ed25519 base point
B.EXAMPLES:
sage: B = Ed25519BasePoint() sage: B.parent() is Ed25519() True sage: B.coordinates() == (ED25519_BASE_X, ED25519_BASE_Y) True
>>> from sage.all import * >>> B = Ed25519BasePoint() >>> B.parent() is Ed25519() True >>> B.coordinates() == (ED25519_BASE_X, ED25519_BASE_Y) True
B = Ed25519BasePoint() B.parent() is Ed25519() B.coordinates() == (ED25519_BASE_X, ED25519_BASE_Y)
- class sage.crypto.ed25519.Ed25519SignatureScheme(variant='ed25519', context=b'')[source]¶
Bases:
objectEd25519, Ed25519ctx and Ed25519ph as a digital-signature scheme object.
This is the object-oriented counterpart of the module-level functions: one instance bundles the RFC 8032 variant and (for ctx/ph) the context string, which removes the risk of signing and verifying with mismatched domain parameters. When the digital-signature framework of Issue #42856 is available, this class is a
DigitalSignatureBasesubclass and can be used uniformly with the other schemes of that framework.INPUT:
variant– one of'ed25519','ed25519ctx','ed25519ph'context– bytes-like application context (at most 255 bytes), only used by the'ed25519ctx'and'ed25519ph'variants; ignored for pure Ed25519
Keys are the RFC 8032 32-byte seed (secret) and 32-byte encoded point (public). Messages are bytes-like; Ed25519ph hashes them with SHA-512 internally, so pass the raw message, not its prehash.
EXAMPLES:
sage: from sage.crypto.ed25519 import Ed25519SignatureScheme sage: ed = Ed25519SignatureScheme('ed25519ph', b'foo') sage: secret = ed.secret_key() sage: public = ed.public_key(secret) sage: signature, signed_message = ed.sign(b'attack at dawn', secret) sage: ed.verify(public, signature, signed_message) True
>>> from sage.all import * >>> from sage.crypto.ed25519 import Ed25519SignatureScheme >>> ed = Ed25519SignatureScheme('ed25519ph', b'foo') >>> secret = ed.secret_key() >>> public = ed.public_key(secret) >>> signature, signed_message = ed.sign(b'attack at dawn', secret) >>> ed.verify(public, signature, signed_message) True
from sage.crypto.ed25519 import Ed25519SignatureScheme ed = Ed25519SignatureScheme('ed25519ph', b'foo') secret = ed.secret_key() public = ed.public_key(secret) signature, signed_message = ed.sign(b'attack at dawn', secret) ed.verify(public, signature, signed_message)A signature made under one context does not verify under another:
sage: other = Ed25519SignatureScheme('ed25519ph', b'bar') sage: other.verify(public, signature, signed_message) False
>>> from sage.all import * >>> other = Ed25519SignatureScheme('ed25519ph', b'bar') >>> other.verify(public, signature, signed_message) False
other = Ed25519SignatureScheme('ed25519ph', b'bar') other.verify(public, signature, signed_message)The pure variant reproduces the RFC 8032 section 7.1 test vector:
sage: pure = Ed25519SignatureScheme('ed25519') sage: seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') sage: signature, _ = pure.sign(b'', seed) sage: signature.hex() 'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
>>> from sage.all import * >>> pure = Ed25519SignatureScheme('ed25519') >>> seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') >>> signature, _ = pure.sign(b'', seed) >>> signature.hex() 'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
pure = Ed25519SignatureScheme('ed25519') seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') signature, _ = pure.sign(b'', seed) signature.hex()- public_key(secret_key)[source]¶
Return the 32-byte public key of a 32-byte seed.
EXAMPLES:
sage: from sage.crypto.ed25519 import Ed25519SignatureScheme sage: ed = Ed25519SignatureScheme() sage: seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') sage: ed.public_key(seed).hex() 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
>>> from sage.all import * >>> from sage.crypto.ed25519 import Ed25519SignatureScheme >>> ed = Ed25519SignatureScheme() >>> seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') >>> ed.public_key(seed).hex() 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
from sage.crypto.ed25519 import Ed25519SignatureScheme ed = Ed25519SignatureScheme() seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') ed.public_key(seed).hex()
- secret_key()[source]¶
Return a fresh random 32-byte Ed25519 seed.
EXAMPLES:
sage: from sage.crypto.ed25519 import Ed25519SignatureScheme sage: ed = Ed25519SignatureScheme() sage: sk = ed.secret_key() sage: len(sk) 32
>>> from sage.all import * >>> from sage.crypto.ed25519 import Ed25519SignatureScheme >>> ed = Ed25519SignatureScheme() >>> sk = ed.secret_key() >>> len(sk) 32
from sage.crypto.ed25519 import Ed25519SignatureScheme ed = Ed25519SignatureScheme() sk = ed.secret_key() len(sk)
- sign(message, secret_key, nonce=None)[source]¶
Sign
messagewith a 32-byte seed and return(signature, message).Ed25519 nonces are derived deterministically from the secret key and the message, so an explicit
nonceis not supported; the parameter is accepted and ignored to keep the signature-shape of the framework.EXAMPLES:
sage: from sage.crypto.ed25519 import Ed25519SignatureScheme sage: ed = Ed25519SignatureScheme('ed25519ctx', b'foo') sage: seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') sage: message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') sage: signature, signed = ed.sign(message, seed) sage: signature.hex() == ed25519ctx_sign(seed, message, b'foo').hex() True
>>> from sage.all import * >>> from sage.crypto.ed25519 import Ed25519SignatureScheme >>> ed = Ed25519SignatureScheme('ed25519ctx', b'foo') >>> seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') >>> message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') >>> signature, signed = ed.sign(message, seed) >>> signature.hex() == ed25519ctx_sign(seed, message, b'foo').hex() True
from sage.crypto.ed25519 import Ed25519SignatureScheme ed = Ed25519SignatureScheme('ed25519ctx', b'foo') seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') signature, signed = ed.sign(message, seed) signature.hex() == ed25519ctx_sign(seed, message, b'foo').hex()
- verify(public_key, signature, message)[source]¶
Return whether
signatureis a valid signature ofmessage.EXAMPLES:
sage: from sage.crypto.ed25519 import Ed25519SignatureScheme sage: ed = Ed25519SignatureScheme('ed25519ph') sage: seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') sage: public = ed.public_key(seed) sage: signature, message = ed.sign(b'abc', seed) sage: ed.verify(public, signature, message) True sage: ed.verify(public, signature, b'abd') False
>>> from sage.all import * >>> from sage.crypto.ed25519 import Ed25519SignatureScheme >>> ed = Ed25519SignatureScheme('ed25519ph') >>> seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') >>> public = ed.public_key(seed) >>> signature, message = ed.sign(b'abc', seed) >>> ed.verify(public, signature, message) True >>> ed.verify(public, signature, b'abd') False
from sage.crypto.ed25519 import Ed25519SignatureScheme ed = Ed25519SignatureScheme('ed25519ph') seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') public = ed.public_key(seed) signature, message = ed.sign(b'abc', seed) ed.verify(public, signature, message) ed.verify(public, signature, b'abd')
- sage.crypto.ed25519.ed25519_decode(data)[source]¶
Decode a canonical 32-byte Ed25519 point encoding.
The square root is recovered in
GF(2^255 - 19)using thep = 5 mod 8square-root method. The returned point is a point on the full curve; callers that need a prime-order point must apply the protocol’s cofactor handling.EXAMPLES:
sage: ed25519_decode(bytes.fromhex('5866666666666666666666666666666666666666666666666666666666666666')) == Ed25519BasePoint() True sage: ed25519_decode(b'\xff' * 32) Traceback (most recent call last): ... ValueError: the encoded y-coordinate is not canonical
>>> from sage.all import * >>> ed25519_decode(bytes.fromhex('5866666666666666666666666666666666666666666666666666666666666666')) == Ed25519BasePoint() True >>> ed25519_decode(b'\xff' * Integer(32)) Traceback (most recent call last): ... ValueError: the encoded y-coordinate is not canonical
ed25519_decode(bytes.fromhex('5866666666666666666666666666666666666666666666666666666666666666')) == Ed25519BasePoint() ed25519_decode(b'\xff' * 32)
- sage.crypto.ed25519.ed25519_encode(point)[source]¶
Encode an Ed25519 point as 32 little-endian bytes.
The low 255 bits encode the affine
ycoordinate and the high bit encodes the least significant bit ofx. Coordinates are required to be canonical field elements andpointmust belong toEd25519().EXAMPLES:
sage: ed25519_encode(Ed25519BasePoint()).hex() '5866666666666666666666666666666666666666666666666666666666666666' sage: ed25519_decode(ed25519_encode(Ed25519BasePoint())) == Ed25519BasePoint() True
>>> from sage.all import * >>> ed25519_encode(Ed25519BasePoint()).hex() '5866666666666666666666666666666666666666666666666666666666666666' >>> ed25519_decode(ed25519_encode(Ed25519BasePoint())) == Ed25519BasePoint() True
ed25519_encode(Ed25519BasePoint()).hex() ed25519_decode(ed25519_encode(Ed25519BasePoint())) == Ed25519BasePoint()
- sage.crypto.ed25519.ed25519_public_key(seed)[source]¶
Derive the 32-byte Ed25519 public key from a 32-byte seed.
EXAMPLES:
sage: seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') sage: ed25519_public_key(seed).hex() 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
>>> from sage.all import * >>> seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') >>> ed25519_public_key(seed).hex() 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'
seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') ed25519_public_key(seed).hex()
- sage.crypto.ed25519.ed25519_sign(seed, message)[source]¶
Create a deterministic pure Ed25519 signature.
seedis the 32-byte private-key seed andmessageis a bytes-like message. The result is the 64-byte concatenationENC(R) || ENC(S).EXAMPLES:
sage: seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') sage: ed25519_sign(seed, b'').hex() 'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
>>> from sage.all import * >>> seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') >>> ed25519_sign(seed, b'').hex() 'e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b'
seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') ed25519_sign(seed, b'').hex()
- sage.crypto.ed25519.ed25519_verify(public_key, message, signature)[source]¶
Verify an Ed25519 signature.
The RFC 8032 verification equation is checked with the cofactor:
\[[8][S]B = [8]R + [8][k]A,\]where
kis the reduced SHA-512 challenge. Malformed encodings and non-canonicalSvalues returnFalse.EXAMPLES:
sage: seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') sage: public_key = ed25519_public_key(seed) sage: signature = ed25519_sign(seed, b'') sage: ed25519_verify(public_key, b'', signature) True sage: ed25519_verify(public_key, b'bad', signature) False sage: import operator sage: ed25519_verify(public_key, b'', signature[:-1] + bytes([operator.xor(signature[-1], 1)])) False
>>> from sage.all import * >>> seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') >>> public_key = ed25519_public_key(seed) >>> signature = ed25519_sign(seed, b'') >>> ed25519_verify(public_key, b'', signature) True >>> ed25519_verify(public_key, b'bad', signature) False >>> import operator >>> ed25519_verify(public_key, b'', signature[:-Integer(1)] + bytes([operator.xor(signature[-Integer(1)], Integer(1))])) False
seed = bytes.fromhex('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60') public_key = ed25519_public_key(seed) signature = ed25519_sign(seed, b'') ed25519_verify(public_key, b'', signature) ed25519_verify(public_key, b'bad', signature) import operator ed25519_verify(public_key, b'', signature[:-1] + bytes([operator.xor(signature[-1], 1)]))
- sage.crypto.ed25519.ed25519ctx_sign(seed, message, context)[source]¶
Create an Ed25519ctx signature with a context of at most 255 bytes.
An empty context is permitted, but still uses the Ed25519ctx domain and does not produce a pure Ed25519 signature. The context is bytes-like and must match exactly when verifying.
EXAMPLES:
sage: seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') sage: message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') sage: ed25519ctx_sign(seed, message, b'foo').hex() # RFC 8032, Section 7.2 '55a4cc2f70a54e04288c5f4cd1e45a7bb520b36292911876cada7323198dd87a8b36950b95130022907a7fb7c4e9b2d5f6cca685a587b4b21f4b888e4e7edb0d' sage: ed25519ctx_sign(seed, message, b'bar').hex() 'fc60d5872fc46b3aa69f8b5b4351d5808f92bcc044606db097abab6dbcb1aee3216c48e8b3b66431b5b186d1d28f8ee15a5ca2df6668346291c2043d4eb3e90d'
>>> from sage.all import * >>> seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') >>> message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') >>> ed25519ctx_sign(seed, message, b'foo').hex() # RFC 8032, Section 7.2 '55a4cc2f70a54e04288c5f4cd1e45a7bb520b36292911876cada7323198dd87a8b36950b95130022907a7fb7c4e9b2d5f6cca685a587b4b21f4b888e4e7edb0d' >>> ed25519ctx_sign(seed, message, b'bar').hex() 'fc60d5872fc46b3aa69f8b5b4351d5808f92bcc044606db097abab6dbcb1aee3216c48e8b3b66431b5b186d1d28f8ee15a5ca2df6668346291c2043d4eb3e90d'
seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') ed25519ctx_sign(seed, message, b'foo').hex() # RFC 8032, Section 7.2 ed25519ctx_sign(seed, message, b'bar').hex()
- sage.crypto.ed25519.ed25519ctx_verify(public_key, message, signature, context)[source]¶
Verify an Ed25519ctx signature under the given context.
Return
Falsefor malformed input or a context longer than 255 bytes.EXAMPLES:
sage: seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') sage: public_key = ed25519_public_key(seed) sage: message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') sage: signature = ed25519ctx_sign(seed, message, b'foo') sage: ed25519ctx_verify(public_key, message, signature, b'foo') True sage: ed25519ctx_verify(public_key, message, signature, b'bar') False sage: ed25519_verify(public_key, message, signature) False sage: ed25519ctx_verify(public_key, message, signature, b'x' * 256) False
>>> from sage.all import * >>> seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') >>> public_key = ed25519_public_key(seed) >>> message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') >>> signature = ed25519ctx_sign(seed, message, b'foo') >>> ed25519ctx_verify(public_key, message, signature, b'foo') True >>> ed25519ctx_verify(public_key, message, signature, b'bar') False >>> ed25519_verify(public_key, message, signature) False >>> ed25519ctx_verify(public_key, message, signature, b'x' * Integer(256)) False
seed = bytes.fromhex('0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6') public_key = ed25519_public_key(seed) message = bytes.fromhex('f726936d19c800494e3fdaff20b276a8') signature = ed25519ctx_sign(seed, message, b'foo') ed25519ctx_verify(public_key, message, signature, b'foo') ed25519ctx_verify(public_key, message, signature, b'bar') ed25519_verify(public_key, message, signature) ed25519ctx_verify(public_key, message, signature, b'x' * 256)
- sage.crypto.ed25519.ed25519ph_sign(seed, message, context=b'')[source]¶
Create an Ed25519ph signature of a raw message.
The message is hashed once with SHA-512 before the Ed25519ph nonce and challenge hashes. Do not prehash it before calling this function.
contextis bytes-like, defaults to empty, and is limited to 255 bytes.EXAMPLES:
sage: seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') sage: ed25519ph_sign(seed, b'abc').hex() # RFC 8032, Section 7.3 '98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406' sage: import hashlib sage: ed25519ph_sign(seed, b'abc') != ed25519_sign(seed, hashlib.sha512(b'abc').digest()) True
>>> from sage.all import * >>> seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') >>> ed25519ph_sign(seed, b'abc').hex() # RFC 8032, Section 7.3 '98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406' >>> import hashlib >>> ed25519ph_sign(seed, b'abc') != ed25519_sign(seed, hashlib.sha512(b'abc').digest()) True
seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') ed25519ph_sign(seed, b'abc').hex() # RFC 8032, Section 7.3 import hashlib ed25519ph_sign(seed, b'abc') != ed25519_sign(seed, hashlib.sha512(b'abc').digest())
- sage.crypto.ed25519.ed25519ph_verify(public_key, message, signature, context=b'')[source]¶
Verify an Ed25519ph signature of a raw message.
contextdefaults to empty and must contain at most 255 bytes. ReturnFalsefor malformed input.EXAMPLES:
sage: seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') sage: public_key = ed25519_public_key(seed) sage: signature = ed25519ph_sign(seed, b'abc') sage: ed25519ph_verify(public_key, b'abc', signature) True sage: ed25519ph_verify(public_key, b'abd', signature) False sage: ed25519ph_verify(public_key, b'abc', signature, b'foo') False sage: ed25519_verify(public_key, b'abc', signature) False
>>> from sage.all import * >>> seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') >>> public_key = ed25519_public_key(seed) >>> signature = ed25519ph_sign(seed, b'abc') >>> ed25519ph_verify(public_key, b'abc', signature) True >>> ed25519ph_verify(public_key, b'abd', signature) False >>> ed25519ph_verify(public_key, b'abc', signature, b'foo') False >>> ed25519_verify(public_key, b'abc', signature) False
seed = bytes.fromhex('833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42') public_key = ed25519_public_key(seed) signature = ed25519ph_sign(seed, b'abc') ed25519ph_verify(public_key, b'abc', signature) ed25519ph_verify(public_key, b'abd', signature) ed25519ph_verify(public_key, b'abc', signature, b'foo') ed25519_verify(public_key, b'abc', signature)