From 0e2ec97424602ac89fcf63f0f614f0a644665f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 25 Jun 2025 16:54:48 +0200 Subject: [PATCH] ecdsa: expose coordinates bytes with fixed sizes --- crypto/p256/key.go | 9 ++++++--- crypto/p256/public.go | 14 ++++++++++++++ crypto/p384/key.go | 9 ++++++--- crypto/p384/public.go | 14 ++++++++++++++ crypto/p521/key.go | 9 ++++++--- crypto/p521/public.go | 14 ++++++++++++++ verifications/jsonwebkey/jwk.go | 13 +++++++------ 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/crypto/p256/key.go b/crypto/p256/key.go index fe33c06..e14433d 100644 --- a/crypto/p256/key.go +++ b/crypto/p256/key.go @@ -8,13 +8,16 @@ import ( const ( // PublicKeyBytesSize is the size, in bytes, of public keys in raw bytes. - PublicKeyBytesSize = 33 + PublicKeyBytesSize = 1 + coordinateSize // PrivateKeyBytesSize is the size, in bytes, of private keys in raw bytes. - PrivateKeyBytesSize = 32 + PrivateKeyBytesSize = coordinateSize // SignatureBytesSize is the size, in bytes, of signatures in raw bytes. - SignatureBytesSize = 64 + SignatureBytesSize = 2 * coordinateSize MultibaseCode = uint64(0x1200) + + // coordinateSize is the size, in bytes, of one coordinate in the elliptic curve. + coordinateSize = 32 ) func GenerateKeyPair() (*PublicKey, *PrivateKey, error) { diff --git a/crypto/p256/public.go b/crypto/p256/public.go index db9b445..e9b894a 100644 --- a/crypto/p256/public.go +++ b/crypto/p256/public.go @@ -74,6 +74,20 @@ func PublicKeyFromX509PEM(str string) (*PublicKey, error) { return PublicKeyFromX509DER(block.Bytes) } +func (p *PublicKey) XBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).X.FillBytes(buf[:]) + return buf[:] +} + +func (p *PublicKey) YBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).Y.FillBytes(buf[:]) + return buf[:] +} + func (p *PublicKey) Equal(other crypto.PublicKey) bool { if other, ok := other.(*PublicKey); ok { return p.k.Equal(other.k) diff --git a/crypto/p384/key.go b/crypto/p384/key.go index f9c4a3c..88deef1 100644 --- a/crypto/p384/key.go +++ b/crypto/p384/key.go @@ -8,13 +8,16 @@ import ( const ( // PublicKeyBytesSize is the size, in bytes, of public keys in raw bytes. - PublicKeyBytesSize = 49 + PublicKeyBytesSize = 1 + coordinateSize // PrivateKeyBytesSize is the size, in bytes, of private keys in raw bytes. - PrivateKeyBytesSize = 48 + PrivateKeyBytesSize = coordinateSize // SignatureBytesSize is the size, in bytes, of signatures in raw bytes. - SignatureBytesSize = 96 + SignatureBytesSize = 2 * coordinateSize MultibaseCode = uint64(0x1201) + + // coordinateSize is the size, in bytes, of one coordinate in the elliptic curve. + coordinateSize = 48 ) func GenerateKeyPair() (*PublicKey, *PrivateKey, error) { diff --git a/crypto/p384/public.go b/crypto/p384/public.go index 96499e6..1909d7a 100644 --- a/crypto/p384/public.go +++ b/crypto/p384/public.go @@ -74,6 +74,20 @@ func PublicKeyFromX509PEM(str string) (*PublicKey, error) { return PublicKeyFromX509DER(block.Bytes) } +func (p *PublicKey) XBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).X.FillBytes(buf[:]) + return buf[:] +} + +func (p *PublicKey) YBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).Y.FillBytes(buf[:]) + return buf[:] +} + func (p *PublicKey) Equal(other crypto.PublicKey) bool { if other, ok := other.(*PublicKey); ok { return p.k.Equal(other.k) diff --git a/crypto/p521/key.go b/crypto/p521/key.go index ced58f6..7569396 100644 --- a/crypto/p521/key.go +++ b/crypto/p521/key.go @@ -8,13 +8,16 @@ import ( const ( // PublicKeyBytesSize is the size, in bytes, of public keys in raw bytes. - PublicKeyBytesSize = 67 + PublicKeyBytesSize = 1 + coordinateSize // PrivateKeyBytesSize is the size, in bytes, of private keys in raw bytes. - PrivateKeyBytesSize = 66 + PrivateKeyBytesSize = coordinateSize // SignatureBytesSize is the size, in bytes, of signatures in raw bytes. - SignatureBytesSize = 132 + SignatureBytesSize = 2 * coordinateSize MultibaseCode = uint64(0x1202) + + // coordinateSize is the size, in bytes, of one coordinate in the elliptic curve. + coordinateSize = 66 ) func GenerateKeyPair() (*PublicKey, *PrivateKey, error) { diff --git a/crypto/p521/public.go b/crypto/p521/public.go index fc26bb7..d4cad54 100644 --- a/crypto/p521/public.go +++ b/crypto/p521/public.go @@ -74,6 +74,20 @@ func PublicKeyFromX509PEM(str string) (*PublicKey, error) { return PublicKeyFromX509DER(block.Bytes) } +func (p *PublicKey) XBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).X.FillBytes(buf[:]) + return buf[:] +} + +func (p *PublicKey) YBytes() []byte { + // fixed size buffer that can get allocated on the caller's stack after inlining. + var buf [coordinateSize]byte + (p.k).Y.FillBytes(buf[:]) + return buf[:] +} + func (p *PublicKey) Equal(other crypto.PublicKey) bool { if other, ok := other.(*PublicKey); ok { return p.k.Equal(other.k) diff --git a/verifications/jsonwebkey/jwk.go b/verifications/jsonwebkey/jwk.go index 308f786..1ffd8aa 100644 --- a/verifications/jsonwebkey/jwk.go +++ b/verifications/jsonwebkey/jwk.go @@ -10,6 +10,7 @@ import ( "github.com/INFURA/go-did/crypto/ed25519" "github.com/INFURA/go-did/crypto/p256" "github.com/INFURA/go-did/crypto/p384" + "github.com/INFURA/go-did/crypto/p521" "github.com/INFURA/go-did/crypto/x25519" ) @@ -42,8 +43,8 @@ func (j jwk) MarshalJSON() ([]byte, error) { }{ Kty: "EC", Crv: "P-256", - X: base64.RawURLEncoding.EncodeToString(pubkey.X.Bytes()), - Y: base64.RawURLEncoding.EncodeToString(pubkey.Y.Bytes()), + X: base64.RawURLEncoding.EncodeToString(pubkey.XBytes()), + Y: base64.RawURLEncoding.EncodeToString(pubkey.YBytes()), }) case *p384.PublicKey: return json.Marshal(struct { @@ -54,8 +55,8 @@ func (j jwk) MarshalJSON() ([]byte, error) { }{ Kty: "EC", Crv: "P-384", - X: base64.RawURLEncoding.EncodeToString(pubkey.X.Bytes()), - Y: base64.RawURLEncoding.EncodeToString(pubkey.Y.Bytes()), + X: base64.RawURLEncoding.EncodeToString(pubkey.XBytes()), + Y: base64.RawURLEncoding.EncodeToString(pubkey.YBytes()), }) case *p521.PublicKey: return json.Marshal(struct { @@ -66,8 +67,8 @@ func (j jwk) MarshalJSON() ([]byte, error) { }{ Kty: "EC", Crv: "P-521", - X: base64.RawURLEncoding.EncodeToString(pubkey.X.Bytes()), - Y: base64.RawURLEncoding.EncodeToString(pubkey.Y.Bytes()), + X: base64.RawURLEncoding.EncodeToString(pubkey.XBytes()), + Y: base64.RawURLEncoding.EncodeToString(pubkey.YBytes()), }) case *x25519.PublicKey: return json.Marshal(struct {