예제 #1
0
func (c *crypter) Generate(key, salt []byte) (string, error) {
	if len(salt) == 0 {
		salt = c.Salt.GenerateWRounds(SaltLenMax, RoundsDefault)
	}
	salt, rounds, isRoundsDef, _, err := c.Salt.Decode(salt)
	if err != nil {
		return "", err
	}

	keyLen := len(key)
	saltLen := len(salt)
	h := sha512.New()

	// compute sumB
	// step 4-8
	h.Write(key)
	h.Write(salt)
	h.Write(key)
	sumB := h.Sum(nil)

	// Compute sumA
	// step 1-3, 9-12
	h.Reset()
	h.Write(key)
	h.Write(salt)
	h.Write(internal.RepeatByteSequence(sumB, keyLen))
	for i := keyLen; i > 0; i >>= 1 {
		if i%2 == 0 {
			h.Write(key)
		} else {
			h.Write(sumB)
		}
	}
	sumA := h.Sum(nil)
	internal.CleanSensitiveData(sumB)

	// Compute seqP
	// step 13-16
	h.Reset()
	for i := 0; i < keyLen; i++ {
		h.Write(key)
	}
	seqP := internal.RepeatByteSequence(h.Sum(nil), keyLen)

	// Compute seqS
	// step 17-20
	h.Reset()
	for i := 0; i < 16+int(sumA[0]); i++ {
		h.Write(salt)
	}
	seqS := internal.RepeatByteSequence(h.Sum(nil), saltLen)

	// step 21
	for i := 0; i < rounds; i++ {
		h.Reset()

		if i&1 != 0 {
			h.Write(seqP)
		} else {
			h.Write(sumA)
		}
		if i%3 != 0 {
			h.Write(seqS)
		}
		if i%7 != 0 {
			h.Write(seqP)
		}
		if i&1 != 0 {
			h.Write(sumA)
		} else {
			h.Write(seqP)
		}
		copy(sumA, h.Sum(nil))
	}
	internal.CleanSensitiveData(seqP)
	internal.CleanSensitiveData(seqS)

	// make output
	buf := bytes.Buffer{}
	buf.Grow(len(c.Salt.MagicPrefix) + len(_rounds) + 9 + 1 + len(salt) + 1 + 86)
	buf.Write(c.Salt.MagicPrefix)
	if isRoundsDef {
		buf.Write(_rounds)
		buf.WriteString(strconv.Itoa(rounds))
		buf.WriteByte('$')
	}
	buf.Write(salt)
	buf.WriteByte('$')
	buf.Write(common.Base64_24Bit([]byte{
		sumA[42], sumA[21], sumA[0],
		sumA[1], sumA[43], sumA[22],
		sumA[23], sumA[2], sumA[44],
		sumA[45], sumA[24], sumA[3],
		sumA[4], sumA[46], sumA[25],
		sumA[26], sumA[5], sumA[47],
		sumA[48], sumA[27], sumA[6],
		sumA[7], sumA[49], sumA[28],
		sumA[29], sumA[8], sumA[50],
		sumA[51], sumA[30], sumA[9],
		sumA[10], sumA[52], sumA[31],
		sumA[32], sumA[11], sumA[53],
		sumA[54], sumA[33], sumA[12],
		sumA[13], sumA[55], sumA[34],
		sumA[35], sumA[14], sumA[56],
		sumA[57], sumA[36], sumA[15],
		sumA[16], sumA[58], sumA[37],
		sumA[38], sumA[17], sumA[59],
		sumA[60], sumA[39], sumA[18],
		sumA[19], sumA[61], sumA[40],
		sumA[41], sumA[20], sumA[62],
		sumA[63],
	}))
	return buf.String(), nil
}
예제 #2
0
func (c *crypter) Generate(key, salt []byte) (result string, err error) {
	if len(salt) == 0 {
		salt = c.Salt.Generate(SaltLenMax)
	}
	salt, _, _, _, err = c.Salt.Decode(salt)
	if err != nil {
		return
	}

	keyLen := len(key)
	h := md5.New()

	// Compute sumB
	h.Write(key)
	h.Write(salt)
	h.Write(key)
	sumB := h.Sum(nil)

	// Compute sumA
	h.Reset()
	h.Write(key)
	h.Write(c.Salt.MagicPrefix)
	h.Write(salt)
	h.Write(internal.RepeatByteSequence(sumB, keyLen))
	// The original implementation now does something weird:
	//   For every 1 bit in the key, the first 0 is added to the buffer
	//   For every 0 bit, the first character of the key
	// This does not seem to be what was intended but we have to follow this to
	// be compatible.
	for i := keyLen; i > 0; i >>= 1 {
		if i%2 == 0 {
			h.Write(key[0:1])
		} else {
			h.Write([]byte{0})
		}
	}
	sumA := h.Sum(nil)
	internal.CleanSensitiveData(sumB)

	// In fear of password crackers here comes a quite long loop which just
	// processes the output of the previous round again.
	// We cannot ignore this here.
	for i := 0; i < RoundsDefault; i++ {
		h.Reset()

		// Add key or last result.
		if i%2 != 0 {
			h.Write(key)
		} else {
			h.Write(sumA)
		}
		// Add salt for numbers not divisible by 3.
		if i%3 != 0 {
			h.Write(salt)
		}
		// Add key for numbers not divisible by 7.
		if i%7 != 0 {
			h.Write(key)
		}
		// Add key or last result.
		if i&1 != 0 {
			h.Write(sumA)
		} else {
			h.Write(key)
		}
		copy(sumA, h.Sum(nil))
	}

	buf := bytes.Buffer{}
	buf.Grow(len(c.Salt.MagicPrefix) + len(salt) + 1 + 22)
	buf.Write(c.Salt.MagicPrefix)
	buf.Write(salt)
	buf.WriteByte('$')
	buf.Write(common.Base64_24Bit([]byte{
		sumA[12], sumA[6], sumA[0],
		sumA[13], sumA[7], sumA[1],
		sumA[14], sumA[8], sumA[2],
		sumA[15], sumA[9], sumA[3],
		sumA[5], sumA[10], sumA[4],
		sumA[11],
	}))
	return buf.String(), nil
}