Blame vendor/golang.org/x/crypto/pkcs12/pbkdf.go

Packit 63bb0d
// Copyright 2015 The Go Authors. All rights reserved.
Packit 63bb0d
// Use of this source code is governed by a BSD-style
Packit 63bb0d
// license that can be found in the LICENSE file.
Packit 63bb0d
Packit 63bb0d
package pkcs12
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"bytes"
Packit 63bb0d
	"crypto/sha1"
Packit 63bb0d
	"math/big"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
var (
Packit 63bb0d
	one = big.NewInt(1)
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// sha1Sum returns the SHA-1 hash of in.
Packit 63bb0d
func sha1Sum(in []byte) []byte {
Packit 63bb0d
	sum := sha1.Sum(in)
Packit 63bb0d
	return sum[:]
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of
Packit 63bb0d
// repeats of pattern.
Packit 63bb0d
func fillWithRepeats(pattern []byte, v int) []byte {
Packit 63bb0d
	if len(pattern) == 0 {
Packit 63bb0d
		return nil
Packit 63bb0d
	}
Packit 63bb0d
	outputLen := v * ((len(pattern) + v - 1) / v)
Packit 63bb0d
	return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen]
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
Packit 63bb0d
	// implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
Packit 63bb0d
Packit 63bb0d
	//    Let H be a hash function built around a compression function f:
Packit 63bb0d
Packit 63bb0d
	//       Z_2^u x Z_2^v -> Z_2^u
Packit 63bb0d
Packit 63bb0d
	//    (that is, H has a chaining variable and output of length u bits, and
Packit 63bb0d
	//    the message input to the compression function of H is v bits).  The
Packit 63bb0d
	//    values for u and v are as follows:
Packit 63bb0d
Packit 63bb0d
	//            HASH FUNCTION     VALUE u        VALUE v
Packit 63bb0d
	//              MD2, MD5          128            512
Packit 63bb0d
	//                SHA-1           160            512
Packit 63bb0d
	//               SHA-224          224            512
Packit 63bb0d
	//               SHA-256          256            512
Packit 63bb0d
	//               SHA-384          384            1024
Packit 63bb0d
	//               SHA-512          512            1024
Packit 63bb0d
	//             SHA-512/224        224            1024
Packit 63bb0d
	//             SHA-512/256        256            1024
Packit 63bb0d
Packit 63bb0d
	//    Furthermore, let r be the iteration count.
Packit 63bb0d
Packit 63bb0d
	//    We assume here that u and v are both multiples of 8, as are the
Packit 63bb0d
	//    lengths of the password and salt strings (which we denote by p and s,
Packit 63bb0d
	//    respectively) and the number n of pseudorandom bits required.  In
Packit 63bb0d
	//    addition, u and v are of course non-zero.
Packit 63bb0d
Packit 63bb0d
	//    For information on security considerations for MD5 [19], see [25] and
Packit 63bb0d
	//    [1], and on those for MD2, see [18].
Packit 63bb0d
Packit 63bb0d
	//    The following procedure can be used to produce pseudorandom bits for
Packit 63bb0d
	//    a particular "purpose" that is identified by a byte called "ID".
Packit 63bb0d
	//    This standard specifies 3 different values for the ID byte:
Packit 63bb0d
Packit 63bb0d
	//    1.  If ID=1, then the pseudorandom bits being produced are to be used
Packit 63bb0d
	//        as key material for performing encryption or decryption.
Packit 63bb0d
Packit 63bb0d
	//    2.  If ID=2, then the pseudorandom bits being produced are to be used
Packit 63bb0d
	//        as an IV (Initial Value) for encryption or decryption.
Packit 63bb0d
Packit 63bb0d
	//    3.  If ID=3, then the pseudorandom bits being produced are to be used
Packit 63bb0d
	//        as an integrity key for MACing.
Packit 63bb0d
Packit 63bb0d
	//    1.  Construct a string, D (the "diversifier"), by concatenating v/8
Packit 63bb0d
	//        copies of ID.
Packit 63bb0d
	var D []byte
Packit 63bb0d
	for i := 0; i < v; i++ {
Packit 63bb0d
		D = append(D, ID)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	//    2.  Concatenate copies of the salt together to create a string S of
Packit 63bb0d
	//        length v(ceiling(s/v)) bits (the final copy of the salt may be
Packit 63bb0d
	//        truncated to create S).  Note that if the salt is the empty
Packit 63bb0d
	//        string, then so is S.
Packit 63bb0d
Packit 63bb0d
	S := fillWithRepeats(salt, v)
Packit 63bb0d
Packit 63bb0d
	//    3.  Concatenate copies of the password together to create a string P
Packit 63bb0d
	//        of length v(ceiling(p/v)) bits (the final copy of the password
Packit 63bb0d
	//        may be truncated to create P).  Note that if the password is the
Packit 63bb0d
	//        empty string, then so is P.
Packit 63bb0d
Packit 63bb0d
	P := fillWithRepeats(password, v)
Packit 63bb0d
Packit 63bb0d
	//    4.  Set I=S||P to be the concatenation of S and P.
Packit 63bb0d
	I := append(S, P...)
Packit 63bb0d
Packit 63bb0d
	//    5.  Set c=ceiling(n/u).
Packit 63bb0d
	c := (size + u - 1) / u
Packit 63bb0d
Packit 63bb0d
	//    6.  For i=1, 2, ..., c, do the following:
Packit 63bb0d
	A := make([]byte, c*20)
Packit 63bb0d
	var IjBuf []byte
Packit 63bb0d
	for i := 0; i < c; i++ {
Packit 63bb0d
		//        A.  Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
Packit 63bb0d
		//            H(H(H(... H(D||I))))
Packit 63bb0d
		Ai := hash(append(D, I...))
Packit 63bb0d
		for j := 1; j < r; j++ {
Packit 63bb0d
			Ai = hash(Ai)
Packit 63bb0d
		}
Packit 63bb0d
		copy(A[i*20:], Ai[:])
Packit 63bb0d
Packit 63bb0d
		if i < c-1 { // skip on last iteration
Packit 63bb0d
			// B.  Concatenate copies of Ai to create a string B of length v
Packit 63bb0d
			//     bits (the final copy of Ai may be truncated to create B).
Packit 63bb0d
			var B []byte
Packit 63bb0d
			for len(B) < v {
Packit 63bb0d
				B = append(B, Ai[:]...)
Packit 63bb0d
			}
Packit 63bb0d
			B = B[:v]
Packit 63bb0d
Packit 63bb0d
			// C.  Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
Packit 63bb0d
			//     blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
Packit 63bb0d
			//     setting I_j=(I_j+B+1) mod 2^v for each j.
Packit 63bb0d
			{
Packit 63bb0d
				Bbi := new(big.Int).SetBytes(B)
Packit 63bb0d
				Ij := new(big.Int)
Packit 63bb0d
Packit 63bb0d
				for j := 0; j < len(I)/v; j++ {
Packit 63bb0d
					Ij.SetBytes(I[j*v : (j+1)*v])
Packit 63bb0d
					Ij.Add(Ij, Bbi)
Packit 63bb0d
					Ij.Add(Ij, one)
Packit 63bb0d
					Ijb := Ij.Bytes()
Packit 63bb0d
					// We expect Ijb to be exactly v bytes,
Packit 63bb0d
					// if it is longer or shorter we must
Packit 63bb0d
					// adjust it accordingly.
Packit 63bb0d
					if len(Ijb) > v {
Packit 63bb0d
						Ijb = Ijb[len(Ijb)-v:]
Packit 63bb0d
					}
Packit 63bb0d
					if len(Ijb) < v {
Packit 63bb0d
						if IjBuf == nil {
Packit 63bb0d
							IjBuf = make([]byte, v)
Packit 63bb0d
						}
Packit 63bb0d
						bytesShort := v - len(Ijb)
Packit 63bb0d
						for i := 0; i < bytesShort; i++ {
Packit 63bb0d
							IjBuf[i] = 0
Packit 63bb0d
						}
Packit 63bb0d
						copy(IjBuf[bytesShort:], Ijb)
Packit 63bb0d
						Ijb = IjBuf
Packit 63bb0d
					}
Packit 63bb0d
					copy(I[j*v:(j+1)*v], Ijb)
Packit 63bb0d
				}
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	//    7.  Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
Packit 63bb0d
	//        bit string, A.
Packit 63bb0d
Packit 63bb0d
	//    8.  Use the first n bits of A as the output of this entire process.
Packit 63bb0d
	return A[:size]
Packit 63bb0d
Packit 63bb0d
	//    If the above process is being used to generate a DES key, the process
Packit 63bb0d
	//    should be used to create 64 random bits, and the key's parity bits
Packit 63bb0d
	//    should be set after the 64 bits have been produced.  Similar concerns
Packit 63bb0d
	//    hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any
Packit 63bb0d
	//    similar keys with parity bits "built into them".
Packit 63bb0d
}