mirror of https://github.com/portainer/portainer
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io"
|
|
"math/big"
|
|
|
|
chshare "github.com/jpillora/chisel/share"
|
|
)
|
|
|
|
var one = new(big.Int).SetInt64(1)
|
|
|
|
// GenerateGo119CompatibleKey This function is basically copied from chshare.GenerateKey.
|
|
func GenerateGo119CompatibleKey(seed string) ([]byte, error) {
|
|
r := chshare.NewDetermRand([]byte(seed))
|
|
priv, err := ecdsaGenerateKey(elliptic.P256(), r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
b, err := x509.MarshalECPrivateKey(priv)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Unable to marshal ECDSA private key: %w", err)
|
|
}
|
|
return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}), nil
|
|
}
|
|
|
|
// This function is copied from Go1.19
|
|
func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
|
|
params := c.Params()
|
|
// Note that for P-521 this will actually be 63 bits more than the order, as
|
|
// division rounds down, but the extra bit is inconsequential.
|
|
b := make([]byte, params.N.BitLen()/8+8)
|
|
_, err = io.ReadFull(rand, b)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
k = new(big.Int).SetBytes(b)
|
|
n := new(big.Int).Sub(params.N, one)
|
|
k.Mod(k, n)
|
|
k.Add(k, one)
|
|
return
|
|
}
|
|
|
|
// This function is copied from Go1.19
|
|
func ecdsaGenerateKey(c elliptic.Curve, rand io.Reader) (*ecdsa.PrivateKey, error) {
|
|
k, err := randFieldElement(c, rand)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
priv := new(ecdsa.PrivateKey)
|
|
priv.PublicKey.Curve = c
|
|
priv.D = k
|
|
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
|
|
return priv, nil
|
|
}
|