Skip to main content

Module secp256r1

Module secp256r1 

Source
Expand description

P-256 verification, and deliberately no P-256 signing.

atproto accepts two signing curves. This server mints secp256k1 keys and only secp256k1 keys, for the reason the crate documentation gives: k256 normalizes s on the way out and refuses a high s on the way in, and p256 does neither, so a P-256 signer here would emit a malleable signature about half the time and a relay would refuse it.

Verifying is the other direction and the argument does not apply to it. A key that arrives from somewhere else is not ours to normalize; it is ours to judge, and the judgement is the same three questions asked of a secp256k1 signature — a 64-byte compact pair, a low s, and a verification that succeeds. The low-s check that k256 performs internally is written out by hand here, because p256 will happily verify a high-s signature that atproto refuses.

Half of the network’s accounts sign with this curve, so a server that can read another server’s commit needs it. Nothing in this crate can produce one.

use didbot_key::secp256r1;

// A key from the W3C did:key vectors, which mint nothing here.
let key = secp256r1::VerifyingKey::from_did_key(
    "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb",
)?;
assert!(key.to_did_key().starts_with("did:key:zDn"));

Structs§

Signature
A P-256 ECDSA signature over SHA-256, in 64-byte compact r || s form.
VerifyingKey
A P-256 public key that arrived from somewhere else.

Constants§

P256_CODEC 🔒
The multicodec for a P-256 public key.