portainer/portainer

View on GitHub
api/chisel/crypto/crypto.go

Summary

Maintainability
A
0 mins
Test Coverage
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
}