github.com/cactusblossom/fabric-ca@v0.0.0-20200611062428-0082fc643826/lib/tcert/util.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package tcert
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/aes"
    22  	"crypto/cipher"
    23  	"crypto/ecdsa"
    24  	"crypto/rand"
    25  	"crypto/rsa"
    26  	"crypto/x509"
    27  	"encoding/base64"
    28  	"encoding/pem"
    29  	"errors"
    30  	"fmt"
    31  	"io"
    32  	"io/ioutil"
    33  	"math/big"
    34  	"time"
    35  
    36  	"github.com/cloudflare/cfssl/log"
    37  )
    38  
    39  const (
    40  	// AESKeyLength is the default AES key length
    41  	AESKeyLength = 32
    42  )
    43  
    44  var (
    45  	//RootPreKeySize is the default value of root key
    46  	RootPreKeySize = 48
    47  )
    48  
    49  // GenerateIntUUID returns a UUID based on RFC 4122 returning a big.Int
    50  func GenerateIntUUID() (*big.Int, error) {
    51  	uuid, err := GenerateBytesUUID()
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	z := big.NewInt(0)
    56  	return z.SetBytes(uuid), nil
    57  }
    58  
    59  // GenerateBytesUUID returns a UUID based on RFC 4122 returning the generated bytes
    60  func GenerateBytesUUID() ([]byte, error) {
    61  	uuid := make([]byte, 16)
    62  	_, err := io.ReadFull(rand.Reader, uuid)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	// variant bits; see section 4.1.1
    68  	uuid[8] = uuid[8]&^0xc0 | 0x80
    69  
    70  	// version 4 (pseudo-random); see section 4.1.3
    71  	uuid[6] = uuid[6]&^0xf0 | 0x40
    72  
    73  	return uuid, nil
    74  }
    75  
    76  // CBCPKCS7Encrypt combines CBC encryption and PKCS7 padding
    77  func CBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
    78  	return CBCEncrypt(key, PKCS7Padding(src))
    79  }
    80  
    81  // CBCEncrypt encrypts using CBC mode
    82  func CBCEncrypt(key, s []byte) ([]byte, error) {
    83  	// CBC mode works on blocks so plaintexts may need to be padded to the
    84  	// next whole block. For an example of such padding, see
    85  	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
    86  	// assume that the plaintext is already of the correct length.
    87  	if len(s)%aes.BlockSize != 0 {
    88  		return nil, errors.New("CBCEncrypt failure: plaintext is not a multiple of the block size")
    89  	}
    90  
    91  	block, err := aes.NewCipher(key)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	// The IV needs to be unique, but not secure. Therefore it's common to
    97  	// include it at the beginning of the ciphertext.
    98  	ciphertext := make([]byte, aes.BlockSize+len(s))
    99  	iv := ciphertext[:aes.BlockSize]
   100  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
   101  		return nil, fmt.Errorf("CBCEncrypt failure in io.ReadFull: %s", err)
   102  	}
   103  
   104  	mode := cipher.NewCBCEncrypter(block, iv)
   105  	mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
   106  
   107  	// It's important to remember that ciphertexts must be authenticated
   108  	// (i.e. by using crypto/hmac) as well as being encrypted in order to
   109  	// be secure.
   110  	return ciphertext, nil
   111  }
   112  
   113  // PKCS7Padding pads as prescribed by the PKCS7 standard
   114  func PKCS7Padding(src []byte) []byte {
   115  	padding := aes.BlockSize - len(src)%aes.BlockSize
   116  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
   117  	return append(src, padtext...)
   118  }
   119  
   120  //ConvertDERToPEM returns data from DER to PEM format
   121  //DERData is DER
   122  func ConvertDERToPEM(der []byte, datatype string) []byte {
   123  	pemByte := pem.EncodeToMemory(
   124  		&pem.Block{
   125  			Type:  datatype,
   126  			Bytes: der,
   127  		},
   128  	)
   129  	return pemByte
   130  }
   131  
   132  //GenNumber generates random numbers of type *big.Int with fixed length
   133  func GenNumber(numlen *big.Int) (*big.Int, error) {
   134  	lowerBound := new(big.Int).Exp(big.NewInt(10), new(big.Int).Sub(numlen, big.NewInt(1)), nil)
   135  	upperBound := new(big.Int).Exp(big.NewInt(10), numlen, nil)
   136  	randomNum, err := rand.Int(rand.Reader, upperBound)
   137  	if err != nil {
   138  		return nil, fmt.Errorf("Failed to generate random number: %s", err)
   139  	}
   140  	val := new(big.Int).Add(randomNum, lowerBound)
   141  	valMod := new(big.Int).Mod(val, upperBound)
   142  
   143  	if valMod.Cmp(lowerBound) == -1 {
   144  		newval := new(big.Int).Add(valMod, lowerBound)
   145  		return newval, nil
   146  	}
   147  	return valMod, nil
   148  }
   149  
   150  // GetEnrollmentIDFromCert retrieves Enrollment Id from certificate
   151  func GetEnrollmentIDFromCert(ecert *x509.Certificate) string {
   152  	return ecert.Subject.CommonName
   153  }
   154  
   155  //GetCertificate returns interface containing *rsa.PublicKey or ecdsa.PublicKey
   156  func GetCertificate(certificate []byte) (*x509.Certificate, error) {
   157  
   158  	var certificates []*x509.Certificate
   159  	var isvalidCert bool
   160  	var err error
   161  
   162  	block, _ := pem.Decode(certificate)
   163  	if block == nil {
   164  		certificates, err = x509.ParseCertificates(certificate)
   165  		if err != nil {
   166  			log.Error("Certificate Parse failed")
   167  			return nil, errors.New("DER Certificate Parse failed")
   168  		} //else {
   169  		isvalidCert = ValidateCert(certificates[0])
   170  		if !isvalidCert {
   171  			log.Error("Certificate expired")
   172  			return nil, errors.New("Certificate expired")
   173  		}
   174  		//}
   175  	} else {
   176  		certificates, err = x509.ParseCertificates(block.Bytes)
   177  		if err != nil {
   178  			log.Error("PEM Certificatre Parse failed")
   179  			return nil, errors.New("PEM  Certificate Parse failed")
   180  		} //else {
   181  		isvalidCert = ValidateCert(certificates[0])
   182  		if !isvalidCert {
   183  			log.Error("Certificate expired")
   184  			return nil, errors.New("Certificate expired")
   185  		}
   186  		//}
   187  	}
   188  	return certificates[0], nil
   189  
   190  }
   191  
   192  //GetCertitificateSerialNumber returns serial number for Certificate byte
   193  //return -1 , if there is problem with the cert
   194  func GetCertitificateSerialNumber(certificatebyte []byte) (*big.Int, error) {
   195  	certificate, error := GetCertificate(certificatebyte)
   196  	if error != nil {
   197  		log.Error("Not a valid Certificate")
   198  		return big.NewInt(-1), error
   199  	}
   200  	return certificate.SerialNumber, nil
   201  }
   202  
   203  //ValidateCert checks for expiry in the certificate cert
   204  //Does not check for revocation
   205  func ValidateCert(cert *x509.Certificate) bool {
   206  	notBefore := cert.NotBefore
   207  	notAfter := cert.NotAfter
   208  	currentTime := time.Now()
   209  	diffFromExpiry := notAfter.Sub(currentTime)
   210  	diffFromStart := currentTime.Sub(notBefore)
   211  	return ((diffFromExpiry > 0) && (diffFromStart > 0))
   212  }
   213  
   214  // CBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
   215  func CBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
   216  	pt, err := CBCDecrypt(key, src)
   217  	if err != nil {
   218  
   219  		return nil, err
   220  	}
   221  
   222  	original, err := PKCS7UnPadding(pt)
   223  	if err != nil {
   224  
   225  		return nil, err
   226  	}
   227  
   228  	return original, nil
   229  }
   230  
   231  // CBCDecrypt decrypts using CBC mode
   232  func CBCDecrypt(key, src []byte) ([]byte, error) {
   233  	block, err := aes.NewCipher(key)
   234  	if err != nil {
   235  
   236  		return nil, err
   237  	}
   238  
   239  	// The IV needs to be unique, but not secure. Therefore it's common to
   240  	// include it at the beginning of the ciphertext.
   241  	if len(src) < aes.BlockSize {
   242  
   243  		return nil, errors.New("ciphertext too short")
   244  	}
   245  	iv := src[:aes.BlockSize]
   246  	src = src[aes.BlockSize:]
   247  
   248  	// CBC mode always works in whole blocks.
   249  	if len(src)%aes.BlockSize != 0 {
   250  
   251  		return nil, errors.New("ciphertext is not a multiple of the block size")
   252  	}
   253  
   254  	mode := cipher.NewCBCDecrypter(block, iv)
   255  
   256  	// CryptBlocks can work in-place if the two arguments are the same.
   257  	mode.CryptBlocks(src, src)
   258  
   259  	// If the original plaintext lengths are not a multiple of the block
   260  	// size, padding would have to be added when encrypting, which would be
   261  	// removed at this point. For an example, see
   262  	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
   263  	// critical to note that ciphertexts must be authenticated (i.e. by
   264  	// using crypto/hmac) before being decrypted in order to avoid creating
   265  	// a padding oracle.
   266  
   267  	return src, nil
   268  }
   269  
   270  // PKCS7UnPadding unpads as prescribed by the PKCS7 standard
   271  func PKCS7UnPadding(src []byte) ([]byte, error) {
   272  	length := len(src)
   273  	unpadding := int(src[length-1])
   274  
   275  	if unpadding > aes.BlockSize || unpadding == 0 {
   276  		return nil, fmt.Errorf("invalid padding")
   277  	}
   278  
   279  	pad := src[len(src)-unpadding:]
   280  	for i := 0; i < unpadding; i++ {
   281  		if pad[i] != byte(unpadding) {
   282  			return nil, fmt.Errorf("invalid padding")
   283  		}
   284  	}
   285  
   286  	return src[:(length - unpadding)], nil
   287  }
   288  
   289  //CreateRootPreKey method generates root key
   290  func CreateRootPreKey() string {
   291  	var cooked string
   292  	key := make([]byte, RootPreKeySize)
   293  	rand.Reader.Read(key)
   294  	cooked = base64.StdEncoding.EncodeToString(key)
   295  	return cooked
   296  }
   297  
   298  // GetPrivateKey returns ecdsa.PrivateKey or rsa.privateKey object for the private Key Bytes
   299  func GetPrivateKey(buf []byte) (interface{}, error) {
   300  	var err error
   301  	var privateKey interface{}
   302  
   303  	block, _ := pem.Decode(buf)
   304  	if block == nil {
   305  		privateKey, err = ParsePrivateKey(buf)
   306  		if err != nil {
   307  			return nil, fmt.Errorf("Failure parsing DER-encoded private key: %s", err)
   308  		}
   309  	} else {
   310  		privateKey, err = ParsePrivateKey(block.Bytes)
   311  		if err != nil {
   312  			return nil, fmt.Errorf("Failure parsing PEM private key: %s", err)
   313  		}
   314  	}
   315  
   316  	switch privateKey := privateKey.(type) {
   317  	case *rsa.PrivateKey:
   318  		return privateKey, nil
   319  	case *ecdsa.PrivateKey:
   320  		return privateKey, nil
   321  	default:
   322  		return nil, errors.New("Key is neither RSA nor ECDSA")
   323  	}
   324  
   325  }
   326  
   327  // ParsePrivateKey parses private key
   328  func ParsePrivateKey(der []byte) (interface{}, error) {
   329  	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
   330  		return key, nil
   331  	}
   332  	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
   333  		switch key := key.(type) {
   334  		case *rsa.PrivateKey, *ecdsa.PrivateKey:
   335  			return key, nil
   336  		default:
   337  			return nil, errors.New("Key is neither RSA nor ECDSA")
   338  		}
   339  	}
   340  	key, err := x509.ParseECPrivateKey(der)
   341  	if err != nil {
   342  		return nil, fmt.Errorf("Failure parsing private key: %s", err)
   343  	}
   344  	return key, nil
   345  }
   346  
   347  // LoadCert loads a certificate from a file
   348  func LoadCert(path string) (*x509.Certificate, error) {
   349  	certBuf, err := ioutil.ReadFile(path)
   350  	if err != nil {
   351  		return nil, err
   352  	}
   353  	return GetCertificate(certBuf)
   354  }
   355  
   356  // LoadKey loads a private key from a file
   357  func LoadKey(path string) (interface{}, error) {
   358  	keyBuf, err := ioutil.ReadFile(path)
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  	key, err := GetPrivateKey(keyBuf)
   363  	if err != nil {
   364  		return nil, err
   365  	}
   366  	return key, nil
   367  }