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

     1  package pkcs12
     2  
     3  import (
     4  	"crypto/sha1"
     5  	"math/big"
     6  )
     7  
     8  var (
     9  	deriveKeyByAlg = map[string]func(salt, password []byte, iterations int) []byte{
    10  		pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
    11  			return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
    12  		},
    13  		pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
    14  			return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
    15  		},
    16  	}
    17  	deriveIVByAlg = map[string]func(salt, password []byte, iterations int) []byte{
    18  		pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
    19  			return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
    20  		},
    21  		pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
    22  			return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
    23  		},
    24  	}
    25  )
    26  
    27  func sha1Sum(in []byte) []byte {
    28  	sum := sha1.Sum(in)
    29  	return sum[:]
    30  }
    31  
    32  func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
    33  	// implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
    34  
    35  	//    Let H be a hash function built around a compression function f:
    36  
    37  	//       Z_2^u x Z_2^v -> Z_2^u
    38  
    39  	//    (that is, H has a chaining variable and output of length u bits, and
    40  	//    the message input to the compression function of H is v bits).  The
    41  	//    values for u and v are as follows:
    42  
    43  	//            HASH FUNCTION     VALUE u        VALUE v
    44  	//              MD2, MD5          128            512
    45  	//                SHA-1           160            512
    46  	//               SHA-224          224            512
    47  	//               SHA-256          256            512
    48  	//               SHA-384          384            1024
    49  	//               SHA-512          512            1024
    50  	//             SHA-512/224        224            1024
    51  	//             SHA-512/256        256            1024
    52  
    53  	//    Furthermore, let r be the iteration count.
    54  
    55  	//    We assume here that u and v are both multiples of 8, as are the
    56  	//    lengths of the password and salt strings (which we denote by p and s,
    57  	//    respectively) and the number n of pseudorandom bits required.  In
    58  	//    addition, u and v are of course non-zero.
    59  
    60  	//    For information on security considerations for MD5 [19], see [25] and
    61  	//    [1], and on those for MD2, see [18].
    62  
    63  	//    The following procedure can be used to produce pseudorandom bits for
    64  	//    a particular "purpose" that is identified by a byte called "ID".
    65  	//    This standard specifies 3 different values for the ID byte:
    66  
    67  	//    1.  If ID=1, then the pseudorandom bits being produced are to be used
    68  	//        as key material for performing encryption or decryption.
    69  
    70  	//    2.  If ID=2, then the pseudorandom bits being produced are to be used
    71  	//        as an IV (Initial Value) for encryption or decryption.
    72  
    73  	//    3.  If ID=3, then the pseudorandom bits being produced are to be used
    74  	//        as an integrity key for MACing.
    75  
    76  	//    1.  Construct a string, D (the "diversifier"), by concatenating v/8
    77  	//        copies of ID.
    78  	D := []byte{}
    79  	for i := 0; i < v; i++ {
    80  		D = append(D, ID)
    81  	}
    82  
    83  	//    2.  Concatenate copies of the salt together to create a string S of
    84  	//        length v(ceiling(s/v)) bits (the final copy of the salt may be
    85  	//        truncated to create S).  Note that if the salt is the empty
    86  	//        string, then so is S.
    87  
    88  	S := []byte{}
    89  	{
    90  		s := len(salt)
    91  		times := s / v
    92  		if s%v > 0 {
    93  			times++
    94  		}
    95  		for len(S) < times*v {
    96  			S = append(S, salt...)
    97  		}
    98  		S = S[:times*v]
    99  	}
   100  
   101  	//    3.  Concatenate copies of the password together to create a string P
   102  	//        of length v(ceiling(p/v)) bits (the final copy of the password
   103  	//        may be truncated to create P).  Note that if the password is the
   104  	//        empty string, then so is P.
   105  
   106  	P := []byte{}
   107  	{
   108  		s := len(password)
   109  		times := s / v
   110  		if s%v > 0 {
   111  			times++
   112  		}
   113  		for len(P) < times*v {
   114  			P = append(P, password...)
   115  		}
   116  		password = nil
   117  		P = P[:times*v]
   118  	}
   119  
   120  	//    4.  Set I=S||P to be the concatenation of S and P.
   121  	I := append(S, P...)
   122  
   123  	//    5.  Set c=ceiling(n/u).
   124  	c := size / u
   125  	if size%u > 0 {
   126  		c++
   127  	}
   128  
   129  	//    6.  For i=1, 2, ..., c, do the following:
   130  	A := make([]byte, c*20)
   131  	for i := 0; i < c; i++ {
   132  
   133  		//        A.  Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
   134  		//            H(H(H(... H(D||I))))
   135  		Ai := hash(append(D, I...))
   136  		for j := 1; j < r; j++ {
   137  			Ai = hash(Ai[:])
   138  		}
   139  		copy(A[i*20:], Ai[:])
   140  
   141  		if i < c-1 { // skip on last iteration
   142  
   143  			//        B.  Concatenate copies of Ai to create a string B of length v
   144  			//            bits (the final copy of Ai may be truncated to create B).
   145  			B := []byte{}
   146  			for len(B) < v {
   147  				B = append(B, Ai[:]...)
   148  			}
   149  			B = B[:v]
   150  
   151  			//        C.  Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
   152  			//            blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
   153  			//            setting I_j=(I_j+B+1) mod 2^v for each j.
   154  			{
   155  				Bbi := new(big.Int)
   156  				Bbi.SetBytes(B)
   157  
   158  				one := big.NewInt(1)
   159  
   160  				for j := 0; j < len(I)/v; j++ {
   161  					Ij := new(big.Int)
   162  					Ij.SetBytes(I[j*v : (j+1)*v])
   163  					Ij.Add(Ij, Bbi)
   164  					Ij.Add(Ij, one)
   165  					Ijb := Ij.Bytes()
   166  					if len(Ijb) > v {
   167  						Ijb = Ijb[len(Ijb)-v:]
   168  					}
   169  					copy(I[j*v:(j+1)*v], Ijb)
   170  				}
   171  			}
   172  		}
   173  	}
   174  	//    7.  Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
   175  	//        bit string, A.
   176  
   177  	//    8.  Use the first n bits of A as the output of this entire process.
   178  	A = A[:size]
   179  
   180  	return A
   181  
   182  	//    If the above process is being used to generate a DES key, the process
   183  	//    should be used to create 64 random bits, and the key's parity bits
   184  	//    should be set after the 64 bits have been produced.  Similar concerns
   185  	//    hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
   186  	//    similar keys with parity bits "built into them".
   187  }