github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/crypto/crypto.go (about) 1 package crypto 2 3 import ( 4 "bytes" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/hmac" 8 "crypto/rand" 9 "crypto/sha256" 10 "crypto/x509" 11 "encoding/base64" 12 "encoding/binary" 13 "encoding/pem" 14 "errors" 15 "fmt" 16 "math/big" 17 mrand "math/rand" 18 "sync" 19 "time" 20 21 "github.com/ugorji/go/codec" 22 "go.aporeto.io/tg/tglib/windowscertbug" 23 "go.uber.org/zap" 24 ) 25 26 type nonce struct { 27 r *mrand.Rand 28 sync.Mutex 29 } 30 31 // PublicKey is an intermediate structure to create gobs 32 type PublicKey struct { 33 X *big.Int 34 Y *big.Int 35 } 36 37 //Nonce16Byte interface generates 16 byte nonce 38 type Nonce16Byte interface { 39 GenerateNonce16Bytes([]byte) 40 } 41 42 var doOnce sync.Once 43 var n nonce 44 45 // Nonce initializes and returns nonce of type Nonce16Byte. 46 func Nonce() Nonce16Byte { 47 doOnce.Do(func() { 48 n.r = mrand.New(mrand.NewSource(time.Now().UnixNano())) 49 }) 50 51 return &n 52 } 53 54 func (n *nonce) GenerateNonce16Bytes(b []byte) { 55 n.Lock() 56 low := n.r.Uint64() 57 high := n.r.Uint64() 58 n.Unlock() 59 60 binary.LittleEndian.PutUint64(b[:8], low) 61 binary.LittleEndian.PutUint64(b[8:], high) 62 } 63 64 // ComputeHmac256 computes the HMAC256 of the message 65 func ComputeHmac256(tags []byte, key []byte) ([]byte, error) { 66 67 var buffer bytes.Buffer 68 if err := binary.Write(&buffer, binary.BigEndian, tags); err != nil { 69 return []byte{}, err 70 } 71 72 h := hmac.New(sha256.New, key) 73 74 if _, err := h.Write(buffer.Bytes()); err != nil { 75 return []byte{}, err 76 } 77 78 return h.Sum(nil), nil 79 80 } 81 82 // VerifyHmac verifies if the HMAC of the message matches the one provided 83 func VerifyHmac(tags []byte, expectedMAC []byte, key []byte) bool { 84 messageMAC, err := ComputeHmac256(tags, key) 85 if err != nil { 86 return false 87 } 88 89 return hmac.Equal(messageMAC, expectedMAC) 90 } 91 92 // GenerateRandomBytes returns securely generated random bytes. 93 // It will return an error if the system's secure random 94 // number generator fails to function correctly, in which 95 // case the caller should not continue. 96 func GenerateRandomBytes(n int) ([]byte, error) { 97 b := make([]byte, n) 98 99 if _, err := rand.Read(b); err != nil { 100 zap.L().Debug("GenerateRandomBytes failed", zap.Error(err)) 101 return nil, err 102 } 103 104 s := base64.StdEncoding.EncodeToString(b) 105 106 return []byte(s[:n]), nil 107 } 108 109 // GenerateRandomString returns a URL-safe, base64 encoded 110 // securely generated random string. 111 // It will return an error if the system's secure random 112 // number generator fails to function correctly, in which 113 // case the caller should not continue. 114 func GenerateRandomString(s int) (string, error) { 115 b, err := GenerateRandomBytes(s) 116 return base64.URLEncoding.EncodeToString(b), err 117 } 118 119 // CreateEphemeralKey creates an ephmeral private/public key based on the 120 // provided public key and the corresponding elliptic curve 121 func CreateEphemeralKey(curve func() elliptic.Curve, pub *ecdsa.PublicKey) (*ecdsa.PrivateKey, []byte) { 122 123 ephemeral, err := ecdsa.GenerateKey(curve(), rand.Reader) 124 if err != nil { 125 zap.L().Error("CreateEphemeralKey failed, returning empty array of bytes", zap.Error(err)) 126 return nil, []byte{} 127 } 128 129 ephPub := elliptic.Marshal(pub.Curve, ephemeral.PublicKey.X, ephemeral.PublicKey.Y) 130 131 return ephemeral, ephPub 132 133 } 134 135 // LoadRootCertificates loads the certificates in the provide PEM buffer in a CertPool 136 func LoadRootCertificates(rootPEM []byte) *x509.CertPool { 137 138 roots := x509.NewCertPool() 139 140 ok := roots.AppendCertsFromPEM(rootPEM) 141 if !ok { 142 zap.L().Error("AppendCertsFromPEM failed", zap.ByteString("rootPEM", rootPEM)) 143 return nil 144 } 145 146 return roots 147 148 } 149 150 // LoadEllipticCurveKey parses and creates an EC key 151 func LoadEllipticCurveKey(keyPEM []byte) (*ecdsa.PrivateKey, error) { 152 153 block, _ := pem.Decode(keyPEM) 154 if block == nil { 155 return nil, fmt.Errorf("LoadElliticCurveKey bad pem block: %s", string(keyPEM)) 156 } 157 158 // Parse the key 159 key, err := x509.ParseECPrivateKey(block.Bytes) 160 if err != nil { 161 return nil, err 162 } 163 164 return key, nil 165 } 166 167 // LoadAndVerifyCertificate parses, validates, and creates a certificate structure from a PEM buffer 168 // It must be provided with the a CertPool 169 func LoadAndVerifyCertificate(certPEM []byte, roots *x509.CertPool) (*x509.Certificate, error) { 170 171 cert, err := LoadCertificate(certPEM) 172 if err != nil { 173 return nil, err 174 } 175 176 opts := x509.VerifyOptions{ 177 Roots: roots, 178 } 179 180 if _, err := windowscertbug.VerifyCertificate(cert, opts); err != nil { 181 return nil, err 182 } 183 184 return cert, nil 185 186 } 187 188 // LoadAndVerifyECSecrets loads all the certificates and keys to memory in the right data structures 189 func LoadAndVerifyECSecrets(keyPEM, certPEM, caCertPEM []byte) (key *ecdsa.PrivateKey, cert *x509.Certificate, rootCertPool *x509.CertPool, err error) { 190 191 // Parse the key 192 key, err = LoadEllipticCurveKey(keyPEM) 193 if err != nil { 194 return nil, nil, nil, err 195 } 196 197 rootCertPool = LoadRootCertificates(caCertPEM) 198 if rootCertPool == nil { 199 return nil, nil, nil, errors.New("unable to load root certificate pool") 200 } 201 202 cert, err = LoadAndVerifyCertificate(certPEM, rootCertPool) 203 if err != nil { 204 return nil, nil, nil, err 205 } 206 207 return key, cert, rootCertPool, nil 208 209 } 210 211 // LoadCertificate loads a certificate from a PEM file without verifying 212 // Should only be used for loading a root CA certificate. It will only read 213 // the first certificate 214 func LoadCertificate(certPEM []byte) (*x509.Certificate, error) { 215 216 // Decode the certificate 217 certBlock, _ := pem.Decode(certPEM) 218 if certBlock == nil { 219 return nil, fmt.Errorf("unable to parse pem block: %s", string(certPEM)) 220 } 221 222 // Create the certificate structure 223 cert, err := x509.ParseCertificate(certBlock.Bytes) 224 if err != nil { 225 return nil, err 226 } 227 228 return cert, nil 229 } 230 231 //EncodePublicKeyV1 encodes the public key to a byte slice 232 func EncodePublicKeyV1(publicKey *ecdsa.PublicKey) []byte { 233 234 p := &PublicKey{X: publicKey.X, Y: publicKey.Y} 235 236 buf := make([]byte, 0, 1400) 237 var h codec.Handle = new(codec.CborHandle) 238 enc := codec.NewEncoderBytes(&buf, h) 239 240 if err := enc.Encode(p); err != nil { 241 return nil 242 } 243 244 return buf 245 246 } 247 248 // DecodePublicKeyV1 decodes the provided public key 249 func DecodePublicKeyV1(key []byte) (*ecdsa.PublicKey, error) { 250 var p PublicKey 251 252 var h codec.Handle = new(codec.CborHandle) 253 254 dec := codec.NewDecoderBytes(key, h) 255 if err := dec.Decode(&p); err != nil { 256 return nil, err 257 } 258 259 return &ecdsa.PublicKey{ 260 Curve: elliptic.P256(), 261 X: p.X, 262 Y: p.Y, 263 }, nil 264 } 265 266 //EncodePublicKeyV2 encodes the public key to a byte slice 267 func EncodePublicKeyV2(publicKey *ecdsa.PublicKey) []byte { 268 return elliptic.Marshal(publicKey.Curve, publicKey.X, publicKey.Y) 269 } 270 271 // DecodePublicKeyV2 decodes the provided public key 272 func DecodePublicKeyV2(key []byte) (*ecdsa.PublicKey, error) { 273 274 x, y := elliptic.Unmarshal(elliptic.P256(), key) 275 if x == nil || y == nil { 276 return nil, fmt.Errorf("Failed to decode public key") 277 } 278 279 return &ecdsa.PublicKey{ 280 Curve: elliptic.P256(), 281 X: x, 282 Y: y, 283 }, nil 284 } 285 286 //EncodePrivateKey encodes the private key to a byte slice. 287 func EncodePrivateKey(privateKey *ecdsa.PrivateKey) []byte { 288 return elliptic.Marshal(privateKey.PublicKey.Curve, privateKey.D, privateKey.PublicKey.X) 289 }