···3636 RejectMalleable: true,
3737}
38383939+var k256LenientOptions = &secp256k1secec.ECDSAOptions{
4040+ // Used to *verify* digest, not to re-hash
4141+ Hash: crypto.SHA256,
4242+ // Use `[R | S]` encoding.
4343+ Encoding: secp256k1secec.EncodingCompact,
4444+ // Allows (eg, for JWT validation)
4545+ RejectMalleable: false,
4646+}
4747+3948// Creates a secure new cryptographic key from scratch, with the indicated curve type.
4049func GeneratePrivateKeyK256() (*PrivateKeyK256, error) {
4150 key, err := secp256k1secec.GenerateKey()
···182191func (k *PublicKeyK256) HashAndVerify(content, sig []byte) error {
183192 hash := sha256.Sum256(content)
184193 if !k.pubK256.Verify(hash[:], sig, k256Options) {
194194+ return ErrInvalidSignature
195195+ }
196196+ return nil
197197+}
198198+199199+// Same as HashAndVerify(), only does not require "low-S" signature.
200200+//
201201+// Used for, eg, JWT validation.
202202+func (k *PublicKeyK256) HashAndVerifyLenient(content, sig []byte) error {
203203+ hash := sha256.Sum256(content)
204204+ if !k.pubK256.Verify(hash[:], sig, k256LenientOptions) {
185205 return ErrInvalidSignature
186206 }
187207 return nil
+3
atproto/crypto/keys.go
···4343 // Hashes the raw bytes using SHA-256, then verifies the signature of the digest bytes.
4444 HashAndVerify(content, sig []byte) error
45454646+ // Same as HashAndVerify(), only does not require "low-S" signature. Used for, eg, JWT validation.
4747+ HashAndVerifyLenient(content, sig []byte) error
4848+4649 // String serialization of the key bytes using common parameters:
4750 // compressed byte serialization; multicode varint code prefix; base58btc
4851 // string encoding ("z" prefix)
+21
atproto/crypto/p256.go
···226226 return nil
227227}
228228229229+// Same as HashAndVerify(), only does not require "low-S" signature.
230230+//
231231+// Used for, eg, JWT validation.
232232+func (k *PublicKeyP256) HashAndVerifyLenient(content, sig []byte) error {
233233+ hash := sha256.Sum256(content)
234234+ // parseP256Sig
235235+ if len(sig) != 64 {
236236+ return fmt.Errorf("crypto: P-256 signatures must be 64 bytes, got len=%d", len(sig))
237237+ }
238238+ r := big.NewInt(0)
239239+ s := big.NewInt(0)
240240+ r.SetBytes(sig[:32])
241241+ s.SetBytes(sig[32:])
242242+243243+ if !ecdsa.Verify(&k.pubP256, hash[:], r, s) {
244244+ return ErrInvalidSignature
245245+ }
246246+247247+ return nil
248248+}
249249+229250// Multibase string encoding of the public key, including a multicodec indicator and compressed curve bytes serialization
230251func (k *PublicKeyP256) Multibase() string {
231252 kbytes := k.Bytes()