Bỏ qua để đến nội dung

Mẫu code ES256

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
}
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
}
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
}