github.com/kubri/kubri@v0.5.1-0.20240317001612-bda2aaef967e/pkg/crypto/dsa/dsa.go (about)

     1  package dsa
     2  
     3  import (
     4  	"crypto/dsa"
     5  	"crypto/rand"
     6  	"crypto/sha1"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/asn1"
    10  	"encoding/pem"
    11  	"math/big"
    12  
    13  	"github.com/kubri/kubri/pkg/crypto"
    14  )
    15  
    16  type (
    17  	PrivateKey = dsa.PrivateKey
    18  	PublicKey  = dsa.PublicKey
    19  )
    20  
    21  type privateKey struct {
    22  	Version       int
    23  	P, Q, G, Y, X *big.Int
    24  }
    25  
    26  type signature struct {
    27  	R, S *big.Int
    28  }
    29  
    30  // Sign signs the data with the private key.
    31  func Sign(key *PrivateKey, data []byte) ([]byte, error) {
    32  	if key == nil {
    33  		return nil, crypto.ErrInvalidKey
    34  	}
    35  	sum := sha1.Sum(data)
    36  	r, s, err := dsa.Sign(rand.Reader, key, sum[:])
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	return asn1.Marshal(signature{r, s})
    41  }
    42  
    43  // Verify verifies the signature of the data with the public key.
    44  func Verify(key *PublicKey, data, sig []byte) bool {
    45  	if key == nil {
    46  		return false
    47  	}
    48  	var s signature
    49  	if _, err := asn1.Unmarshal(sig, &s); err != nil {
    50  		return false
    51  	}
    52  	sum := sha1.Sum(data)
    53  	return dsa.Verify(key, sum[:], s.R, s.S)
    54  }
    55  
    56  // NewPrivateKey returns a new private key.
    57  func NewPrivateKey() (*PrivateKey, error) {
    58  	var key PrivateKey
    59  	err := dsa.GenerateParameters(&key.Parameters, rand.Reader, dsa.L3072N256)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	err = dsa.GenerateKey(&key, rand.Reader)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	return &key, nil
    68  }
    69  
    70  // MarshalPrivateKey returns the PEM encoded private key.
    71  func MarshalPrivateKey(key *PrivateKey) ([]byte, error) {
    72  	if key == nil {
    73  		return nil, crypto.ErrInvalidKey
    74  	}
    75  	b, err := asn1.Marshal(privateKey{0, key.P, key.Q, key.G, key.Y, key.X})
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: b}), nil
    80  }
    81  
    82  // UnmarshalPrivateKey returns a private key from a PEM encoded key.
    83  func UnmarshalPrivateKey(b []byte) (*PrivateKey, error) {
    84  	block, _ := pem.Decode(b)
    85  	if block == nil {
    86  		return nil, crypto.ErrInvalidKey
    87  	}
    88  	var k privateKey
    89  	if _, err := asn1.Unmarshal(block.Bytes, &k); err != nil {
    90  		return nil, crypto.ErrInvalidKey
    91  	}
    92  
    93  	return &dsa.PrivateKey{
    94  		PublicKey: dsa.PublicKey{
    95  			Parameters: dsa.Parameters{P: k.P, Q: k.Q, G: k.G},
    96  			Y:          k.Y,
    97  		},
    98  		X: k.X,
    99  	}, nil
   100  }
   101  
   102  // Public extracts the public key from a private key.
   103  func Public(key *PrivateKey) *PublicKey {
   104  	return &key.PublicKey
   105  }
   106  
   107  // MarshalPublicKey returns the PEM encoded public key.
   108  func MarshalPublicKey(key *PublicKey) ([]byte, error) {
   109  	if key == nil {
   110  		return nil, crypto.ErrInvalidKey
   111  	}
   112  
   113  	var pub struct {
   114  		Algo      pkix.AlgorithmIdentifier
   115  		BitString asn1.BitString
   116  	}
   117  	pub.Algo.Algorithm = []int{1, 2, 840, 10040, 4, 1}
   118  	pub.Algo.Parameters.FullBytes, _ = asn1.Marshal(key.Parameters)
   119  	pub.BitString.Bytes, _ = asn1.Marshal(key.Y)
   120  	pub.BitString.BitLength = len(pub.BitString.Bytes) * 8
   121  
   122  	b, err := asn1.Marshal(pub)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	return pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: b}), nil
   128  }
   129  
   130  // UnmarshalPublicKey returns a public key from a PEM encoded key.
   131  func UnmarshalPublicKey(b []byte) (*PublicKey, error) {
   132  	block, _ := pem.Decode(b)
   133  	if block == nil {
   134  		return nil, crypto.ErrInvalidKey
   135  	}
   136  	key, err := x509.ParsePKIXPublicKey(block.Bytes)
   137  	if err != nil {
   138  		return nil, crypto.ErrInvalidKey
   139  	}
   140  	dsaKey, ok := key.(*PublicKey)
   141  	if !ok {
   142  		return nil, crypto.ErrWrongKeyType
   143  	}
   144  	return dsaKey, nil
   145  }