internal/providers/aws: Refactor deprecated crypto/elliptic APIs to crypto/ecdh (#8395)

Following SA1019 deprecation warnings in Go 1.21+, the legacy curve.ScalarBaseMult
and curve.IsOnCurve calls for NIST curves (like P256) are substituted with
their crypto/ecdh standard equivalents. Tests continue to parse and verify AWS V4a
signatures equivalently under the new module constraints.

Signed-off-by: kanywst <niwatakuma@icloud.com>
This commit is contained in:
kt
2026-03-05 23:46:03 +09:00
committed by GitHub
parent 935d92ef92
commit d6ed06cf15
2 changed files with 68 additions and 5 deletions
+55 -4
View File
@@ -2,6 +2,7 @@ package crypto
import (
"bytes"
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
@@ -27,27 +28,77 @@ func ECDSAKey(curve elliptic.Curve, d []byte) *ecdsa.PrivateKey {
// ECDSAKeyFromPoint takes the given elliptic curve and point and returns the
// private and public keypair
func ECDSAKeyFromPoint(curve elliptic.Curve, d *big.Int) *ecdsa.PrivateKey {
pX, pY := curve.ScalarBaseMult(d.Bytes())
dBytes := make([]byte, (curve.Params().BitSize+7)/8)
d.FillBytes(dBytes)
privKey := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: pX,
Y: pY,
},
D: d,
}
var pubBytes []byte
switch curve {
case elliptic.P256():
if ecdhPriv, err := ecdh.P256().NewPrivateKey(dBytes); err == nil {
pubBytes = ecdhPriv.PublicKey().Bytes()
}
case elliptic.P384():
if ecdhPriv, err := ecdh.P384().NewPrivateKey(dBytes); err == nil {
pubBytes = ecdhPriv.PublicKey().Bytes()
}
case elliptic.P521():
if ecdhPriv, err := ecdh.P521().NewPrivateKey(dBytes); err == nil {
pubBytes = ecdhPriv.PublicKey().Bytes()
}
}
if len(pubBytes) > 0 {
byteLen := (curve.Params().BitSize + 7) / 8
privKey.X = new(big.Int).SetBytes(pubBytes[1 : 1+byteLen])
privKey.Y = new(big.Int).SetBytes(pubBytes[1+byteLen:])
} else {
panic(fmt.Sprintf("unsupported curve or invalid private key: %v", curve))
}
return privKey
}
// mathIntToBytes writes val as a big-endian, fixed-length byte slice into out,
// zero-padding on the left when val.Bytes() is shorter than out. This satisfies
// the uncompressed SEC 1 encoding (0x04 || X || Y) expected by crypto/ecdh's
// NewPublicKey: https://pkg.go.dev/crypto/ecdh#Curve.NewPublicKey
func mathIntToBytes(val *big.Int, out []byte) {
valBytes := val.Bytes()
copy(out[len(out)-len(valBytes):], valBytes)
}
// ECDSAPublicKey takes the provide curve and (x, y) coordinates and returns
// *ecdsa.PublicKey. Returns an error if the given points are not on the curve.
func ECDSAPublicKey(curve elliptic.Curve, x, y []byte) (*ecdsa.PublicKey, error) {
xPoint := (&big.Int{}).SetBytes(x)
yPoint := (&big.Int{}).SetBytes(y)
if !curve.IsOnCurve(xPoint, yPoint) {
byteLen := (curve.Params().BitSize + 7) / 8
buf := make([]byte, 1+2*byteLen)
buf[0] = 4 // uncompressed point
mathIntToBytes(xPoint, buf[1:1+byteLen])
mathIntToBytes(yPoint, buf[1+byteLen:])
var err error
switch curve {
case elliptic.P256():
_, err = ecdh.P256().NewPublicKey(buf)
case elliptic.P384():
_, err = ecdh.P384().NewPublicKey(buf)
case elliptic.P521():
_, err = ecdh.P521().NewPublicKey(buf)
default:
err = fmt.Errorf("unsupported curve for ECDSA: %v", curve)
}
if err != nil {
return nil, fmt.Errorf("point(%v, %v) is not on the given curve", xPoint.String(), yPoint.String())
}
+13 -1
View File
@@ -4,6 +4,7 @@ package aws
import (
"bytes"
"crypto"
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
@@ -115,7 +116,18 @@ func deriveKeyFromAccessKeyPair(accessKey, secretKey string) (*ecdsa.PrivateKey,
priv := new(ecdsa.PrivateKey)
priv.PublicKey.Curve = p256
priv.D = d
priv.PublicKey.X, priv.PublicKey.Y = p256.ScalarBaseMult(d.Bytes())
dBytes := make([]byte, 32)
d.FillBytes(dBytes)
ecdhPriv, err := ecdh.P256().NewPrivateKey(dBytes)
if err != nil {
return nil, err
}
pubBytes := ecdhPriv.PublicKey().Bytes()
priv.PublicKey.X = new(big.Int).SetBytes(pubBytes[1:33])
priv.PublicKey.Y = new(big.Int).SetBytes(pubBytes[33:])
return priv, nil
}