Bump github.com/go-git/go-git/v5 from 5.4.2 to 5.11.0

Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.4.2 to 5.11.0.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.4.2...v5.11.0)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
This commit is contained in:
dependabot[bot]
2024-01-16 22:54:39 +00:00
committed by GitHub
parent 1736c011f3
commit 524258ed14
456 changed files with 47170 additions and 5150 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ type AEADMode uint8
const (
AEADModeEAX = AEADMode(1)
AEADModeOCB = AEADMode(2)
AEADModeGCM = AEADMode(100)
AEADModeGCM = AEADMode(3)
)
// TagLength returns the length in bytes of authentication tags.
+78 -21
View File
@@ -32,26 +32,25 @@ type Hash interface {
// The following vars mirror the crypto/Hash supported hash functions.
var (
MD5 Hash = cryptoHash{1, crypto.MD5}
SHA1 Hash = cryptoHash{2, crypto.SHA1}
RIPEMD160 Hash = cryptoHash{3, crypto.RIPEMD160}
SHA256 Hash = cryptoHash{8, crypto.SHA256}
SHA384 Hash = cryptoHash{9, crypto.SHA384}
SHA512 Hash = cryptoHash{10, crypto.SHA512}
SHA224 Hash = cryptoHash{11, crypto.SHA224}
SHA1 Hash = cryptoHash{2, crypto.SHA1}
SHA256 Hash = cryptoHash{8, crypto.SHA256}
SHA384 Hash = cryptoHash{9, crypto.SHA384}
SHA512 Hash = cryptoHash{10, crypto.SHA512}
SHA224 Hash = cryptoHash{11, crypto.SHA224}
SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
)
// HashById represents the different hash functions specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
var (
HashById = map[uint8]Hash{
MD5.Id(): MD5,
SHA1.Id(): SHA1,
RIPEMD160.Id(): RIPEMD160,
SHA256.Id(): SHA256,
SHA384.Id(): SHA384,
SHA512.Id(): SHA512,
SHA224.Id(): SHA224,
SHA256.Id(): SHA256,
SHA384.Id(): SHA384,
SHA512.Id(): SHA512,
SHA224.Id(): SHA224,
SHA3_256.Id(): SHA3_256,
SHA3_512.Id(): SHA3_512,
}
)
@@ -68,13 +67,12 @@ func (h cryptoHash) Id() uint8 {
}
var hashNames = map[uint8]string{
MD5.Id(): "MD5",
SHA1.Id(): "SHA1",
RIPEMD160.Id(): "RIPEMD160",
SHA256.Id(): "SHA256",
SHA384.Id(): "SHA384",
SHA512.Id(): "SHA512",
SHA224.Id(): "SHA224",
SHA256.Id(): "SHA256",
SHA384.Id(): "SHA384",
SHA512.Id(): "SHA512",
SHA224.Id(): "SHA224",
SHA3_256.Id(): "SHA3-256",
SHA3_512.Id(): "SHA3-512",
}
func (h cryptoHash) String() string {
@@ -84,3 +82,62 @@ func (h cryptoHash) String() string {
}
return s
}
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
return 0, false
}
// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
// hash id, allowing sha1.
func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
if id == SHA1.Id() {
return SHA1.HashFunc(), true
}
return 0, false
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.String(), true
}
return "", false
}
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
return 0, false
}
// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
// allowing instances of SHA1
func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
if h == SHA1.HashFunc() {
return SHA1.Id(), true
}
return 0, false
}
@@ -0,0 +1,171 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x25519lib "github.com/cloudflare/circl/dh/x25519"
)
type curve25519 struct{}
func NewCurve25519() *curve25519 {
return &curve25519{}
}
func (c *curve25519) GetCurveName() string {
return "curve25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes the public point to native format, removing the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x25519lib.Size+1 {
return nil
}
// Remove prefix
return point[1:]
}
// MarshalByteSecret encodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
// Note that leading zero bytes are stripped later when encoding as an MPI.
func (c *curve25519) MarshalByteSecret(secret []byte) []byte {
d := make([]byte, x25519lib.Size)
copyReversed(d, secret)
// The following ensures that the private key is a number of the form
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
// the curve.
//
// This masking is done internally in the underlying lib and so is unnecessary
// for security, but OpenPGP implementations require that private keys be
// pre-masked.
d[0] &= 127
d[0] |= 64
d[31] &= 248
return d
}
// UnmarshalByteSecret decodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
func (c *curve25519) UnmarshalByteSecret(d []byte) []byte {
if len(d) > x25519lib.Size {
return nil
}
// Ensure truncated leading bytes are re-added
secret := make([]byte, x25519lib.Size)
copyReversed(secret, d)
return secret
}
// generateKeyPairBytes Generates a private-public key-pair.
// 'priv' is a private key; a little-endian scalar belonging to the set
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
// curve. 'pub' is simply 'priv' * G where G is the base point.
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
func (c *curve25519) generateKeyPairBytes(rand io.Reader) (priv, pub x25519lib.Key, err error) {
_, err = io.ReadFull(rand, priv[:])
if err != nil {
return
}
x25519lib.KeyGen(&pub, &priv)
return
}
func (c *curve25519) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *genericCurve) MaskSecret(secret []byte) []byte {
return secret
}
func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
// RFC6637 §8: "Generate an ephemeral key pair {v, V=vG}"
// ephemeralPrivate corresponds to `v`.
// ephemeralPublic corresponds to `V`.
ephemeralPrivate, ephemeralPublic, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
// RFC6637 §8: "Obtain the authenticated recipient public key R"
// pubKey corresponds to `R`.
var pubKey x25519lib.Key
copy(pubKey[:], point)
// RFC6637 §8: "Compute the shared point S = vR"
// "VB = convert point V to the octet string"
// sharedPoint corresponds to `VB`.
var sharedPoint x25519lib.Key
x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
return ephemeralPublic[:], sharedPoint[:], nil
}
func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error) {
var ephemeralPublic, decodedPrivate, sharedPoint x25519lib.Key
// RFC6637 §8: "The decryption is the inverse of the method given."
// All quoted descriptions in comments below describe encryption, and
// the reverse is performed.
// vsG corresponds to `VB` in RFC6637 §8 .
// RFC6637 §8: "VB = convert point V to the octet string"
copy(ephemeralPublic[:], vsG)
// decodedPrivate corresponds to `r` in RFC6637 §8 .
copy(decodedPrivate[:], secret)
// RFC6637 §8: "Note that the recipient obtains the shared secret by calculating
// S = rV = rvG, where (r,R) is the recipient's key pair."
// sharedPoint corresponds to `S`.
x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
return sharedPoint[:], nil
}
func (c *curve25519) ValidateECDH(point []byte, secret []byte) (err error) {
var pk, sk x25519lib.Key
copy(sk[:], secret)
x25519lib.KeyGen(&pk, &sk)
if subtle.ConstantTimeCompare(point, pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}
func copyReversed(out []byte, in []byte) {
l := len(in)
for i := 0; i < l; i++ {
out[i] = in[l-i-1]
}
}
@@ -1,118 +0,0 @@
package ecc
import (
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
"crypto/elliptic"
"bytes"
"github.com/ProtonMail/go-crypto/bitcurves"
"github.com/ProtonMail/go-crypto/brainpool"
)
type SignatureAlgorithm uint8
const (
ECDSA SignatureAlgorithm = 1
EdDSA SignatureAlgorithm = 2
)
type CurveInfo struct {
Name string
Oid *encoding.OID
Curve elliptic.Curve
SigAlgorithm SignatureAlgorithm
CurveType CurveType
}
var curves = []CurveInfo{
{
Name: "NIST curve P-256",
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
Curve: elliptic.P256(),
CurveType: NISTCurve,
SigAlgorithm: ECDSA,
},
{
Name: "NIST curve P-384",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
Curve: elliptic.P384(),
CurveType: NISTCurve,
SigAlgorithm: ECDSA,
},
{
Name: "NIST curve P-521",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
Curve: elliptic.P521(),
CurveType: NISTCurve,
SigAlgorithm: ECDSA,
},
{
Name: "SecP256k1",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
Curve: bitcurves.S256(),
CurveType: BitCurve,
SigAlgorithm: ECDSA,
},
{
Name: "Curve25519",
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
Curve: elliptic.P256(),// filler
CurveType: Curve25519,
SigAlgorithm: ECDSA,
},
{
Name: "Ed25519",
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
Curve: elliptic.P256(), // filler
CurveType: NISTCurve,
SigAlgorithm: EdDSA,
},
{
Name: "Brainpool P256r1",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
Curve: brainpool.P256r1(),
CurveType: BrainpoolCurve,
SigAlgorithm: ECDSA,
},
{
Name: "BrainpoolP384r1",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
Curve: brainpool.P384r1(),
CurveType: BrainpoolCurve,
SigAlgorithm: ECDSA,
},
{
Name: "BrainpoolP512r1",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
Curve: brainpool.P512r1(),
CurveType: BrainpoolCurve,
SigAlgorithm: ECDSA,
},
}
func FindByCurve(curve elliptic.Curve) *CurveInfo {
for _, curveInfo := range curves {
if curveInfo.Curve == curve {
return &curveInfo
}
}
return nil
}
func FindByOid(oid encoding.Field) *CurveInfo {
var rawBytes = oid.Bytes()
for _, curveInfo := range curves {
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
return &curveInfo
}
}
return nil
}
func FindByName(name string) *CurveInfo {
for _, curveInfo := range curves {
if curveInfo.Name == name {
return &curveInfo
}
}
return nil
}
@@ -1,10 +0,0 @@
package ecc
type CurveType uint8
const (
NISTCurve CurveType = 1
Curve25519 CurveType = 2
BitCurve CurveType = 3
BrainpoolCurve CurveType = 4
)
@@ -0,0 +1,140 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/elliptic"
"github.com/ProtonMail/go-crypto/bitcurves"
"github.com/ProtonMail/go-crypto/brainpool"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
)
type CurveInfo struct {
GenName string
Oid *encoding.OID
Curve Curve
}
var Curves = []CurveInfo{
{
// NIST P-256
GenName: "P256",
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
Curve: NewGenericCurve(elliptic.P256()),
},
{
// NIST P-384
GenName: "P384",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
Curve: NewGenericCurve(elliptic.P384()),
},
{
// NIST P-521
GenName: "P521",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
Curve: NewGenericCurve(elliptic.P521()),
},
{
// SecP256k1
GenName: "SecP256k1",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
Curve: NewGenericCurve(bitcurves.S256()),
},
{
// Curve25519
GenName: "Curve25519",
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
Curve: NewCurve25519(),
},
{
// X448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
Curve: NewX448(),
},
{
// Ed25519
GenName: "Curve25519",
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
Curve: NewEd25519(),
},
{
// Ed448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x71}),
Curve: NewEd448(),
},
{
// BrainpoolP256r1
GenName: "BrainpoolP256",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
Curve: NewGenericCurve(brainpool.P256r1()),
},
{
// BrainpoolP384r1
GenName: "BrainpoolP384",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
Curve: NewGenericCurve(brainpool.P384r1()),
},
{
// BrainpoolP512r1
GenName: "BrainpoolP512",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
Curve: NewGenericCurve(brainpool.P512r1()),
},
}
func FindByCurve(curve Curve) *CurveInfo {
for _, curveInfo := range Curves {
if curveInfo.Curve.GetCurveName() == curve.GetCurveName() {
return &curveInfo
}
}
return nil
}
func FindByOid(oid encoding.Field) *CurveInfo {
var rawBytes = oid.Bytes()
for _, curveInfo := range Curves {
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
return &curveInfo
}
}
return nil
}
func FindEdDSAByGenName(curveGenName string) EdDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(EdDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDSAByGenName(curveGenName string) ECDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDHByGenName(curveGenName string) ECDHCurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDHCurve)
if ok {
return curve
}
}
}
return nil
}
+48
View File
@@ -0,0 +1,48 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"io"
"math/big"
)
type Curve interface {
GetCurveName() string
}
type ECDSACurve interface {
Curve
MarshalIntegerPoint(x, y *big.Int) []byte
UnmarshalIntegerPoint([]byte) (x, y *big.Int)
MarshalIntegerSecret(d *big.Int) []byte
UnmarshalIntegerSecret(d []byte) *big.Int
GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error)
Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error)
Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool
ValidateECDSA(x, y *big.Int, secret []byte) error
}
type EdDSACurve interface {
Curve
MarshalBytePoint(x []byte) []byte
UnmarshalBytePoint([]byte) (x []byte)
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
MarshalSignature(sig []byte) (r, s []byte)
UnmarshalSignature(r, s []byte) (sig []byte)
GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error)
Sign(publicKey, privateKey, message []byte) (sig []byte, err error)
Verify(publicKey, message, sig []byte) bool
ValidateEdDSA(publicKey, privateKey []byte) (err error)
}
type ECDHCurve interface {
Curve
MarshalBytePoint([]byte) (encoded []byte)
UnmarshalBytePoint(encoded []byte) []byte
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error)
Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error)
Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error)
ValidateECDH(public []byte, secret []byte) error
}
+112
View File
@@ -0,0 +1,112 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
)
const ed25519Size = 32
type ed25519 struct{}
func NewEd25519() *ed25519 {
return &ed25519{}
}
func (c *ed25519) GetCurveName() string {
return "ed25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalBytePoint(x []byte) []byte {
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed25519lib.PublicKeySize+1 {
return nil
}
// Return unprefixed
return point[1:]
}
// MarshalByteSecret encodes a scalar in native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalByteSecret(d []byte) []byte {
return d
}
// UnmarshalByteSecret decodes a scalar in native format and re-adds the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalByteSecret(s []byte) (d []byte) {
if len(s) > ed25519lib.SeedSize {
return nil
}
// Handle stripped leading zeroes
d = make([]byte, ed25519lib.SeedSize)
copy(d[ed25519lib.SeedSize-len(s):], s)
return
}
// MarshalSignature splits a signature in R and S.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) MarshalSignature(sig []byte) (r, s []byte) {
return sig[:ed25519Size], sig[ed25519Size:]
}
// UnmarshalSignature decodes R and S in the native format, re-adding the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) UnmarshalSignature(r, s []byte) (sig []byte) {
// Check size
if len(r) > 32 || len(s) > 32 {
return nil
}
sig = make([]byte, ed25519lib.SignatureSize)
// Handle stripped leading zeroes
copy(sig[ed25519Size-len(r):ed25519Size], r)
copy(sig[ed25519lib.SignatureSize-len(s):], s)
return sig
}
func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed25519lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed25519lib.SeedSize], nil
}
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
return append(privateKey, publicKey...)
}
func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
sig = ed25519lib.Sign(getEd25519Sk(publicKey, privateKey), message)
return sig, nil
}
func (c *ed25519) Verify(publicKey, message, sig []byte) bool {
return ed25519lib.Verify(publicKey, message, sig)
}
func (c *ed25519) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd25519Sk(publicKey, privateKey)
expectedPriv := ed25519lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed25519 secret")
}
return nil
}
+111
View File
@@ -0,0 +1,111 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed448lib "github.com/cloudflare/circl/sign/ed448"
)
type ed448 struct{}
func NewEd448() *ed448 {
return &ed448{}
}
func (c *ed448) GetCurveName() string {
return "ed448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalBytePoint(x []byte) []byte {
// Return prefixed
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed448lib.PublicKeySize+1 {
return nil
}
// Strip prefix
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalByteSecret(d []byte) []byte {
// Return prefixed
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalByteSecret(s []byte) (d []byte) {
// Check prefixed size
if len(s) != ed448lib.SeedSize+1 {
return nil
}
// Strip prefix
return s[1:]
}
// MarshalSignature splits a signature in R and S, where R is in prefixed native format and
// S is an MPI with value zero.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) MarshalSignature(sig []byte) (r, s []byte) {
return append([]byte{0x40}, sig...), []byte{}
}
// UnmarshalSignature decodes R and S in the native format. Only R is used, in prefixed native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) UnmarshalSignature(r, s []byte) (sig []byte) {
if len(r) != ed448lib.SignatureSize+1 {
return nil
}
return r[1:]
}
func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed448lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed448lib.SeedSize], nil
}
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
return append(privateKey, publicKey...)
}
func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
sig = ed448lib.Sign(getEd448Sk(publicKey, privateKey), message, "")
return sig, nil
}
func (c *ed448) Verify(publicKey, message, sig []byte) bool {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
return ed448lib.Verify(publicKey, message, sig, "")
}
func (c *ed448) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd448Sk(publicKey, privateKey)
expectedPriv := ed448lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed448 secret")
}
return nil
}
+149
View File
@@ -0,0 +1,149 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"io"
"math/big"
)
type genericCurve struct {
Curve elliptic.Curve
}
func NewGenericCurve(c elliptic.Curve) *genericCurve {
return &genericCurve{
Curve: c,
}
}
func (c *genericCurve) GetCurveName() string {
return c.Curve.Params().Name
}
func (c *genericCurve) MarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte {
return elliptic.Marshal(c.Curve, x, y)
}
func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) {
return elliptic.Unmarshal(c.Curve, point)
}
func (c *genericCurve) MarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte {
return d.Bytes()
}
func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int {
return new(big.Int).SetBytes(d)
}
func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) {
secret, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
point = elliptic.Marshal(c.Curve, x, y)
return point, secret, nil
}
func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) {
priv, err := ecdsa.GenerateKey(c.Curve, rand)
if err != nil {
return
}
return priv.X, priv.Y, priv.D, nil
}
func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
panic("invalid point")
}
d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
vsG := elliptic.Marshal(c.Curve, x, y)
zbBig, _ := c.Curve.ScalarMult(xP, yP, d)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return vsG, zb, nil
}
func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
x, y := elliptic.Unmarshal(c.Curve, ephemeral)
zbBig, _ := c.Curve.ScalarMult(x, y, secret)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return zb, nil
}
func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) {
priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}}
return ecdsa.Sign(rand, priv, hash)
}
func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool {
pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}
return ecdsa.Verify(pub, hash, r, s)
}
func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error {
// the public point should not be at infinity (0,0)
zero := new(big.Int)
if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name))
}
// re-derive the public point Q' = (X,Y) = dG
// to compare to declared Q in public key
expectedX, expectedY := c.Curve.ScalarBaseMult(secret)
if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return nil
}
func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error {
return c.validate(xP, yP, secret)
}
func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return c.validate(xP, yP, secret)
}
+105
View File
@@ -0,0 +1,105 @@
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x448lib "github.com/cloudflare/circl/dh/x448"
)
type x448 struct{}
func NewX448() *x448 {
return &x448{}
}
func (c *x448) GetCurveName() string {
return "x448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x448lib.Size+1 {
return nil
}
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) MarshalByteSecret(d []byte) []byte {
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) UnmarshalByteSecret(d []byte) []byte {
if len(d) != x448lib.Size+1 {
return nil
}
// Store without prefix
return d[1:]
}
func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) {
if _, err = rand.Read(sk[:]); err != nil {
return
}
x448lib.KeyGen(&pk, &sk)
return
}
func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
var pk, ss x448lib.Key
seed, e, err := c.generateKeyPairBytes(rand)
copy(pk[:], point)
x448lib.Shared(&ss, &seed, &pk)
return e[:], ss[:], nil
}
func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
var ss, sk, e x448lib.Key
copy(sk[:], secret)
copy(e[:], ephemeral)
x448lib.Shared(&ss, &sk, &e)
return ss[:], nil
}
func (c *x448) ValidateECDH(point []byte, secret []byte) error {
var sk, pk, expectedPk x448lib.Key
copy(pk[:], point)
copy(sk[:], secret)
x448lib.KeyGen(&expectedPk, &sk)
if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}
+1 -1
View File
@@ -32,7 +32,7 @@ func NewOID(bytes []byte) *OID {
panic("encoding: NewOID argument length is reserved")
default:
if len(bytes) > maxOID {
panic("encoding: NewOID argment too large")
panic("encoding: NewOID argument too large")
}
}