Mẫu code ES256
Generate ES256 Key Pair
Phần tiêu đề “Generate ES256 Key Pair”import ( "crypto/ecdsa" "crypto/rand" "crypto/elliptic")
// GenerateP256KeyPair generates a new P-256 ECDSA key pair.func GenerateES256KeyPair() (*ecdsa.PrivateKey, error) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, fmt.Errorf("crypto: generate P-256 key pair: %w", err) } return priv, nil}Sign ES256
Phần tiêu đề “Sign ES256”import ( "crypto/sha256" "crypto/ecdsa")
// p256CoordSize is the byte length of a P-256 field element (256 bits).const p256CoordSize = 32
// jwsSignatureSize is the fixed size of a JOSE ES256 signature: the raw// concatenation of R and S, each zero-padded to 32 bytes (RFC 7518 §3.4).const jwsSignatureSize = 2 * p256CoordSize
// Sign hashes message with SHA-256 and signs it with priv, returning the// signature in JOSE/RFC 7518 ES256 format: the raw concatenation of R and S,// each zero-padded to 32 bytes (64 bytes total). This is NOT ASN.1/DER.func Sign(priv *ecdsa.PrivateKey, message []byte) ([]byte, error) { if priv == nil { return nil, errors.New("crypto: sign: nil private key") } hash := sha256.Sum256(message) r, s, err := ecdsa.Sign(rand.Reader, priv, hash[:]) if err != nil { return nil, fmt.Errorf("crypto: sign: %w", err) } rb := fillBytes32(r) sb := fillBytes32(s) sig := make([]byte, 0, jwsSignatureSize) sig = append(sig, rb[:]...) sig = append(sig, sb[:]...) return sig, nil}
// fillBytes32 left-pads b's big-endian representation with zero bytes to a// fixed 32-byte array, matching the JOSE ES256 fixed-width integer encoding.func fillBytes32(b *big.Int) [p256CoordSize]byte { var out [p256CoordSize]byte b.FillBytes(out[:]) return out}Verify ES256
Phần tiêu đề “Verify ES256”import ( "crypto/sha256" "crypto/x509" "crypto/ecdsa")
// Verify parses pubSPKI as an SPKI-encoded P-256 public key, hashes message// with SHA-256, and verifies signature (in JOSE ES256 raw r||s format)// against it. It returns (false, nil) for a well-formed but invalid// signature, and a non-nil error only for malformed input (bad SPKI bytes,// wrong signature length).func Verify(pubSPKI []byte, message []byte, signature []byte) (bool, error) { pub, err := ParsePublicKeySPKI(pubSPKI) if err != nil { return false, err } if len(signature) != jwsSignatureSize { return false, fmt.Errorf("crypto: verify: signature must be %d bytes, got %d", jwsSignatureSize, len(signature)) } r := new(big.Int).SetBytes(signature[:p256CoordSize]) s := new(big.Int).SetBytes(signature[p256CoordSize:]) hash := sha256.Sum256(message) return ecdsa.Verify(pub, hash[:], r, s), nil}
// ParsePublicKeySPKI decodes an SPKI/PKIX DER-encoded public key previously// produced by MarshalPublicKeySPKI, returning an error if der does not// encode an ECDSA public key.func ParsePublicKeySPKI(der []byte) (*ecdsa.PublicKey, error) { pub, err := x509.ParsePKIXPublicKey(der) if err != nil { return nil, fmt.Errorf("crypto: parse SPKI public key: %w", err) } ecdsaPub, ok := pub.(*ecdsa.PublicKey) if !ok { return nil, fmt.Errorf("crypto: SPKI public key is %T, not *ecdsa.PublicKey", pub) } return ecdsaPub, nil}