github.com/yoctocloud/packer@v0.6.2-0.20160520224004-e11a0a18423f/builder/azure/pkcs12/crypto.go (about)

     1  // implementation of https://tools.ietf.org/html/rfc2898#section-6.1.2
     2  
     3  package pkcs12
     4  
     5  import (
     6  	"bytes"
     7  	"crypto/cipher"
     8  	"crypto/des"
     9  	"crypto/rand"
    10  	"crypto/x509/pkix"
    11  	"encoding/asn1"
    12  	"errors"
    13  	"io"
    14  
    15  	"github.com/mitchellh/packer/builder/azure/pkcs12/rc2"
    16  )
    17  
    18  const (
    19  	pbeWithSHAAnd3KeyTripleDESCBC = "pbeWithSHAAnd3-KeyTripleDES-CBC"
    20  	pbewithSHAAnd40BitRC2CBC      = "pbewithSHAAnd40BitRC2-CBC"
    21  )
    22  
    23  const (
    24  	pbeIterationCount = 2048
    25  	pbeSaltSizeBytes  = 8
    26  )
    27  
    28  var (
    29  	oidPbeWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 1, 3}
    30  	oidPbewithSHAAnd40BitRC2CBC      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 1, 6}
    31  )
    32  
    33  var algByOID = map[string]string{
    34  	oidPbeWithSHAAnd3KeyTripleDESCBC.String(): pbeWithSHAAnd3KeyTripleDESCBC,
    35  	oidPbewithSHAAnd40BitRC2CBC.String():      pbewithSHAAnd40BitRC2CBC,
    36  }
    37  
    38  var blockcodeByAlg = map[string]func(key []byte) (cipher.Block, error){
    39  	pbeWithSHAAnd3KeyTripleDESCBC: des.NewTripleDESCipher,
    40  	pbewithSHAAnd40BitRC2CBC: func(key []byte) (cipher.Block, error) {
    41  		return rc2.New(key, len(key)*8)
    42  	},
    43  }
    44  
    45  type pbeParams struct {
    46  	Salt       []byte
    47  	Iterations int
    48  }
    49  
    50  func pad(src []byte, blockSize int) []byte {
    51  	paddingLength := blockSize - len(src)%blockSize
    52  	paddingText := bytes.Repeat([]byte{byte(paddingLength)}, paddingLength)
    53  	return append(src, paddingText...)
    54  }
    55  
    56  func pbEncrypt(plainText, salt, password []byte, iterations int) (cipherText []byte, err error) {
    57  	_, err = io.ReadFull(rand.Reader, salt)
    58  	if err != nil {
    59  		return nil, errors.New("pkcs12: failed to create a random salt value: " + err.Error())
    60  	}
    61  
    62  	key := deriveKeyByAlg[pbeWithSHAAnd3KeyTripleDESCBC](salt, password, iterations)
    63  	iv := deriveIVByAlg[pbeWithSHAAnd3KeyTripleDESCBC](salt, password, iterations)
    64  
    65  	block, err := des.NewTripleDESCipher(key)
    66  	if err != nil {
    67  		return nil, errors.New("pkcs12: failed to create a block cipher: " + err.Error())
    68  	}
    69  
    70  	paddedPlainText := pad(plainText, block.BlockSize())
    71  
    72  	encrypter := cipher.NewCBCEncrypter(block, iv)
    73  	cipherText = make([]byte, len(paddedPlainText))
    74  	encrypter.CryptBlocks(cipherText, paddedPlainText)
    75  
    76  	return cipherText, nil
    77  }
    78  
    79  type decryptable interface {
    80  	GetAlgorithm() pkix.AlgorithmIdentifier
    81  	GetData() []byte
    82  }