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 }