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 }