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 }