Exemple #1
0
// Tweak generates a new tweak from the mode, hash, salt length (in
// bytes), and any additional data. It provides additional information
// that will complicate an attacker's efforts, and allows a system to
// differentiate between different uses of the Catena function's output.
func Tweak(mode byte, H hash.Hash, saltLen int, ad []byte) ([]byte, error) {
	if mode != ModePassHash && mode != ModeKeyDerivation {
		return nil, ErrInvalidTweakMode
	}

	hashLen := H.Size()
	tweakLen := 5 + hashLen
	var t = make([]byte, 1, tweakLen)
	t[0] = mode

	var tmp uint16 = uint16(H.Size() * 8)
	high := byte(tmp >> 8)
	low := byte(tmp << 8 >> 8)
	t = append(t, high)
	t = append(t, low)

	tmp = uint16(saltLen * 8)
	high = byte(tmp >> 8)
	low = byte(tmp << 8 >> 8)
	t = append(t, high)
	t = append(t, low)

	H.Reset()
	H.Write(ad)
	t = append(t, H.Sum(nil)...)
	H.Reset()
	return t, nil
}
Exemple #2
0
func Encode(k int, h hash.Hash, value []byte, output int) (enc []byte, s [][]byte) {
	s0 := make([]byte, h.Size())

	n := len(value)
	blockcount := n / k

	s = make([][]byte, blockcount)

	for i := 0; i < blockcount; i++ {
		h.Reset()
		if i == 0 {
			h.Write(s0)
		} else {
			h.Write(s[i-1])
		}

		h.Write(value[i*k : (i+1)*k])
		s[i] = h.Sum(make([]byte, 0, h.Size()))
	}

	rng := make([](*RNG), len(s))
	for i := 0; i < len(s); i++ {
		rng[i] = NewRNG(h, s[i])
	}

	enc = make([]byte, output)

	for i := 0; i < output; i++ {
		enc[i] = rng[i%blockcount].Next()
	}

	return
}
Exemple #3
0
// decode uses the given block cipher (in CTR mode) to decrypt the
// data, and validate the hash.  If hash validation fails, an error is
// returned.
func decode(block cipher.Block, hmac hash.Hash, ciphertext []byte) ([]byte, error) {
	if len(ciphertext) < 2*block.BlockSize()+hmac.Size() {
		return nil, LenError
	}

	receivedHmac := ciphertext[len(ciphertext)-hmac.Size():]
	ciphertext = ciphertext[:len(ciphertext)-hmac.Size()]

	hmac.Write(ciphertext)
	if subtle.ConstantTimeCompare(hmac.Sum(nil), receivedHmac) != 1 {
		return nil, HashError
	}

	// split the iv and session bytes
	iv := ciphertext[len(ciphertext)-block.BlockSize():]
	session := ciphertext[:len(ciphertext)-block.BlockSize()]

	stream := cipher.NewCTR(block, iv)
	stream.XORKeyStream(session, session)

	// skip past the iv
	session = session[block.BlockSize():]

	return session, nil
}
Exemple #4
0
// DeriveConcatKDF implements NIST SP 800-56A Concatenation Key Derivation Function. Derives
// key material of keydatalen bits size given Z (sharedSecret), OtherInfo (AlgorithmID |
// PartyUInfo | PartyVInfo | SuppPubInfo | SuppPrivInfo) and hash function
func DeriveConcatKDF(keydatalen int, sharedSecret, algId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo []byte, h hash.Hash) []byte {

	otherInfo := arrays.Concat(algId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo)

	keyLenBytes := keydatalen >> 3

	reps := int(math.Ceil(float64(keyLenBytes) / float64(h.Size())))

	if reps > MaxInt {
		panic("kdf.DeriveConcatKDF: too much iterations (more than 2^32-1).")
	}

	dk := make([]byte, 0, keyLenBytes)

	for counter := 1; counter <= reps; counter++ {
		h.Reset()

		counterBytes := arrays.UInt32ToBytes(uint32(counter))

		h.Write(counterBytes)
		h.Write(sharedSecret)
		h.Write(otherInfo)

		dk = h.Sum(dk)
	}

	return dk[:keyLenBytes]
}
Exemple #5
0
// EncryptOAEP encrypts the given message with RSA-OAEP.
// The message must be no longer than the length of the public modulus less
// twice the hash length plus 2.
func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err os.Error) {
	hash.Reset()
	k := (pub.N.Len() + 7) / 8
	if len(msg) > k-2*hash.Size()-2 {
		err = MessageTooLongError{}
		return
	}

	hash.Write(label)
	lHash := hash.Sum()
	hash.Reset()

	em := make([]byte, k)
	seed := em[1 : 1+hash.Size()]
	db := em[1+hash.Size():]

	copy(db[0:hash.Size()], lHash)
	db[len(db)-len(msg)-1] = 1
	copy(db[len(db)-len(msg):], msg)

	_, err = io.ReadFull(rand, seed)
	if err != nil {
		return
	}

	mgf1XOR(db, hash, seed)
	mgf1XOR(seed, hash, db)

	m := new(big.Int)
	m.SetBytes(em)
	c := encrypt(new(big.Int), pub, m)
	out = c.Bytes()
	return
}
Exemple #6
0
func (s *descbc) Decrypt(salt []byte, algo, usage int, data []byte) ([]byte, error) {
	var h hash.Hash

	switch algo {
	case cryptDesCbcMd5:
		h = md5.New()
	case cryptDesCbcMd4:
		h = md4.New()
	default:
		return nil, ErrProtocol
	}

	if (len(data) & 7) != 0 {
		return nil, ErrProtocol
	}

	iv := [8]byte{}
	b, _ := des.NewCipher(s.key)
	c := cipher.NewCBCDecrypter(b, iv[:])
	c.CryptBlocks(data, data)

	chk := make([]byte, h.Size())
	h.Write(data[:8])
	h.Write(chk) // Just need h.Size() zero bytes instead of the checksum
	h.Write(data[8+len(chk):])
	h.Sum(chk[:0])

	if subtle.ConstantTimeCompare(chk, data[8:8+len(chk)]) != 1 {
		return nil, ErrProtocol
	}

	return data[8+len(chk):], nil
}
Exemple #7
0
func NewHashAppendReader(r io.Reader, h hash.Hash) *HashAppendReader {
	return &HashAppendReader{
		h:   h,
		r:   io.TeeReader(r, h),
		sum: make([]byte, 0, h.Size()),
	}
}
Exemple #8
0
// jssdk 支付签名, signType 只支持 "MD5", "SHA1", 传入其他的值会 panic.
func JsapiSign(appId, timeStamp, nonceStr, packageStr, signType string, apiKey string) string {
	var h hash.Hash
	switch signType {
	case "MD5":
		h = md5.New()
	case "SHA1":
		h = sha1.New()
	default:
		panic("unsupported signType")
	}
	bufw := bufio.NewWriterSize(h, 128)

	// appId
	// nonceStr
	// package
	// signType
	// timeStamp
	bufw.WriteString("appId=")
	bufw.WriteString(appId)
	bufw.WriteString("&nonceStr=")
	bufw.WriteString(nonceStr)
	bufw.WriteString("&package=")
	bufw.WriteString(packageStr)
	bufw.WriteString("&signType=")
	bufw.WriteString(signType)
	bufw.WriteString("&timeStamp=")
	bufw.WriteString(timeStamp)
	bufw.WriteString("&key=")
	bufw.WriteString(apiKey)

	bufw.Flush()
	signature := make([]byte, hex.EncodedLen(h.Size()))
	hex.Encode(signature, h.Sum(nil))
	return string(bytes.ToUpper(signature))
}
Exemple #9
0
func NewRNG(h hash.Hash, seed []byte) (r *RNG) {
	r = new(RNG)
	r.i = 3610617884
	r.h = h
	r.buffer = make([]byte, 0, h.Size())
	r.seed = seed
	return
}
Exemple #10
0
func GenSessionId() string {
	var h hash.Hash = sessHash()
	h.Write(GenRandomBytes(sessEnthropy))
	h.Write([]byte(strconv.FormatInt(time.Now().Unix(), 10)))
	id := make([]byte, 0, h.Size())
	id = h.Sum(id)
	return base64.StdEncoding.EncodeToString(id)
}
Exemple #11
0
func NewHashAppendWriter(w io.Writer, h hash.Hash) *HashAppendWriter {
	return &HashAppendWriter{
		h:      h,
		w:      io.MultiWriter(w, h),
		origWr: w,
		sum:    make([]byte, 0, h.Size()),
	}
}
Exemple #12
0
// GoId creates a UUID object based on timestamps and a hash.
// It will truncate any bytes past the length of the initial hash.
// This creates a UUID based on a Namespace, UniqueName and an existing
// hash.
func GoId(pNs UUID, pName UniqueName, pHash hash.Hash) UUID {
	o := new(UUIDStruct)
	o.size = pHash.Size()
	Digest(o, pNs, pName, pHash)
	now := currentUUIDTimestamp()
	sequence := uint16(seed.Int()) & 0x3FFF
	return formatGoId(o, now, 15, ReservedFuture, sequence)
}
Exemple #13
0
// this is the function which calculates the HTOP code
func calculateToken(counter []byte, digits int, h hash.Hash) string {

	h.Write(counter)
	hashResult := h.Sum(nil)
	result := truncateHash(hashResult, h.Size())

	mod := int32(result % int64(math.Pow10(digits)))

	fmtStr := fmt.Sprintf("%%0%dd", digits)

	return fmt.Sprintf(fmtStr, mod)
}
Exemple #14
0
func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) {
	h.Reset()
	var p [1]byte
	p[0] = prefix
	h.Write(p[:])
	h.Write(in)
	if len(out) == h.Size() {
		h.Sum(out[:0])
	} else {
		digest := h.Sum(nil)
		copy(out, digest)
	}
}
Exemple #15
0
func testWrite(msg string, t *testing.T, h hash.Hash, c *Config) {
	var msg1 []byte
	msg0 := make([]byte, 64)
	for i := range msg0 {
		h.Write(msg0[:i])
		msg1 = append(msg1, msg0[:i]...)
	}
	tag0 := h.Sum(nil)
	tag1 := Sum(msg1, h.Size(), c)

	if !bytes.Equal(tag0, tag1) {
		t.Fatalf("%s\nSum differ from Sum\n Sum: %s \n skein.Sum: %s", msg, hex.EncodeToString(tag0), hex.EncodeToString(tag1))
	}
}
Exemple #16
0
func benchmarkKB(b *testing.B, h hash.Hash) {
	b.SetBytes(1024)
	data := make([]byte, 1024)
	for i := range data {
		data[i] = byte(i)
	}
	in := make([]byte, 0, h.Size())

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		h.Reset()
		h.Write(data)
		h.Sum(in)
	}
}
Exemple #17
0
// New returns a new HMAC hash using the given hash and key.
func New(h hash.Hash, key []byte) hash.Hash {
	if len(key) > padSize {
		// If key is too big, hash it.
		h.Write(key)
		key = h.Sum()
	}
	hm := new(hmac)
	hm.inner = h
	hm.size = h.Size()
	hm.key = make([]byte, len(key))
	for i, k := range key {
		hm.key[i] = k
	}
	hm.tmp = make([]byte, padSize+hm.size)
	hm.Reset()
	return hm
}
Exemple #18
0
func benchmarkHash(b *testing.B, h hash.Hash, l int) {
	m := make([]byte, l)
	tag := make([]byte, 0, h.Size())

	b.SetBytes(int64(l))
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		h.Reset()

		h.Write(m[:l/4])
		h.Write(m[l/4 : l/2])
		h.Write(m[l/2 : 3*l/4])
		h.Write(m[3*l/4:])
		h.Sum(tag)
	}
}
Exemple #19
0
// EncryptOAEP encrypts the given message with RSA-OAEP.
// The message must be no longer than the length of the public modulus less
// twice the hash length plus 2.
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
	if err := checkPub(pub); err != nil {
		return nil, err
	}
	hash.Reset()
	k := (pub.N.BitLen() + 7) / 8
	if len(msg) > k-2*hash.Size()-2 {
		err = ErrMessageTooLong
		return
	}

	hash.Write(label)
	lHash := hash.Sum(nil)
	hash.Reset()

	em := make([]byte, k)
	seed := em[1 : 1+hash.Size()]
	db := em[1+hash.Size():]

	copy(db[0:hash.Size()], lHash)
	db[len(db)-len(msg)-1] = 1
	copy(db[len(db)-len(msg):], msg)

	_, err = io.ReadFull(random, seed)
	if err != nil {
		return
	}

	mgf1XOR(db, hash, seed)
	mgf1XOR(seed, hash, db)

	m := new(big.Int)
	m.SetBytes(em)
	c := encrypt(new(big.Int), pub, m)
	out = c.Bytes()

	if len(out) < k {
		// If the output is too small, we need to left-pad with zeros.
		t := make([]byte, k)
		copy(t[k-len(out):], out)
		out = t
	}

	return
}
Exemple #20
0
// Encode a message with fixed salt, return the encoded message and random salt
func Encode(hash hash.Hash, msg, salt []byte) ([]byte, []byte, error) {
	if hash == nil {
		hash = sha256.New()
	}
	rand, err := rand.B.Alphanumeric(hash.Size())
	if err != nil {
		return nil, nil, err
	}

	return SaltEncode(hash, msg, salt, rand), rand, err
}
Exemple #21
0
// Creates all the non-leaf nodes for a certain height. The number of nodes
// is calculated to be 1/2 the number of nodes in the lower rung.  The newly
// created nodes will reference their Left and Right children.
// Returns the number of nodes added to current
func (self *Tree) generateNodeLevel(below []Node, current []Node,
	h hash.Hash) (uint64, error) {
	h.Reset()
	size := h.Size()
	data := make([]byte, size*2)
	end := (len(below) + (len(below) % 2)) / 2
	for i := 0; i < end; i++ {
		// Concatenate the two children hashes and hash them, if both are
		// available, otherwise reuse the hash from the lone left node
		node := Node{}
		ileft := 2 * i
		iright := 2*i + 1
		left := &below[ileft]
		var right *Node = nil
		if len(below) > iright {
			right = &below[iright]
		}
		if right == nil {
			b := data[:size]
			copy(b, left.Hash)
			node = Node{Hash: b}
		} else {
			copy(data[:size], below[ileft].Hash)
			copy(data[size:], below[iright].Hash)
			var err error
			node, err = NewNode(h, data)
			if err != nil {
				return 0, err
			}
		}
		// Point the new node to its children and save
		node.Left = left
		node.Right = right
		current[i] = node

		// Reset the data slice
		data = data[:]
	}
	return uint64(end), nil
}
Exemple #22
0
func testIntegrity(t *testing.T, h hash.Hash) {
	data := []byte{'1', '2', 3, 4, 5}
	h.Write(data)
	sum := h.Sum()

	if size := h.Size(); size != len(sum) {
		t.Fatalf("Size()=%d but len(Sum())=%d", size, len(sum))
	}

	if a := h.Sum(); !bytes.Equal(sum, a) {
		t.Fatalf("first Sum()=0x%x, second Sum()=0x%x", sum, a)
	}

	h.Reset()
	h.Write(data)
	if a := h.Sum(); !bytes.Equal(sum, a) {
		t.Fatalf("Sum()=0x%x, but after Reset() Sum()=0x%x", sum, a)
	}

	h.Reset()
	h.Write(data[:2])
	h.Write(data[2:])
	if a := h.Sum(); !bytes.Equal(sum, a) {
		t.Fatalf("Sum()=0x%x, but with partial writes, Sum()=0x%x", sum, a)
	}

	switch h.Size() {
	case 4:
		sum32 := h.(hash.Hash32).Sum32()
		if sum32 != binary.BigEndian.Uint32(sum) {
			t.Fatalf("Sum()=0x%x, but Sum32()=0x%x", sum, sum32)
		}
	case 8:
		sum64 := h.(hash.Hash64).Sum64()
		if sum64 != binary.BigEndian.Uint64(sum) {
			t.Fatalf("Sum()=0x%x, but Sum64()=0x%x", sum, sum64)
		}
	}
}
Exemple #23
0
func (s *descbc) Encrypt(salt []byte, usage int, data ...[]byte) []byte {
	var h hash.Hash

	switch s.etype {
	case cryptDesCbcMd5:
		h = md5.New()
	case cryptDesCbcMd4:
		h = md4.New()
	default:
		panic("")
	}

	outsz := 8 + h.Size()
	for _, d := range data {
		outsz += len(d)
	}
	outsz = (outsz + 7) &^ 7
	out := make([]byte, outsz)

	io.ReadFull(rand.Reader, out[:8])

	v := out[8+h.Size():]
	for _, d := range data {
		n := copy(v, d)
		v = v[n:]
	}

	h.Write(out)
	h.Sum(out[:8])

	iv := [8]byte{}
	b, _ := des.NewCipher(s.key)
	c := cipher.NewCBCEncrypter(b, iv[:])
	c.CryptBlocks(out, out)

	return out
}
Exemple #24
0
// SendFile reads a file from disk and streams it to a receiver across a
// MessageStream. If there are sufficient bytes in the keys (at least
// hmacKeySize+aesKeySize), then it will attempt to check the integrity of the
// file with HMAC-SHA256 and decrypt it with AES-CTR-128.
func SendFile(ms util.MessageStream, dir string, filename string, keys []byte) error {
	fullpath := path.Join(dir, filename)
	fileInfo, err := os.Stat(fullpath)
	if err != nil {
		return fmt.Errorf("in SendFile: no file '%s' found: %s", fullpath, err)
	}
	file, err := os.Open(fullpath)
	if err != nil {
		return fmt.Errorf("in SendFile: can't open file '%s': %s", fullpath, err)
	}
	defer file.Close()

	// This encryption scheme uses AES-CTR with HMAC-SHA256 for integrity
	// protection.
	var hm hash.Hash
	var ctr cipher.Stream
	iv := make([]byte, ivSize)
	hasKeys := len(keys) >= minKeySize

	// The variable "left" gives the total number of bytes left to read from
	// the (maybe encrypted) file.
	left := fileInfo.Size()
	buf := make([]byte, bufferSize)
	if hasKeys {
		dec, err := aes.NewCipher(keys[:aesKeySize])
		if err != nil || dec == nil {
			return fmt.Errorf("can't create AES cipher in SendFile: %s", err)
		}
		if _, err := file.Read(iv); err != nil {
			return err
		}
		// Remove the IV from the number of remaining bytes to decrypt.
		left = left - ivSize

		// Take all the remaining key bytes for the HMAC key.
		hm = hmac.New(sha256.New, keys[aesKeySize:])
		hmacSize := hm.Size()

		// The HMAC input starts with the IV.
		hm.Write(iv)

		ctr = cipher.NewCTR(dec, iv)
		if ctr == nil {
			return fmt.Errorf("can't create AES-CTR encryption")
		}

		// Remove the HMAC-SHA256 output from the bytes to check.
		left = left - int64(hmacSize)

		// Secure decryption in this case requires reading the file
		// twice: once to check the MAC, and once to decrypt the bytes.
		// The MAC must be checked before *any* decryption occurs and
		// before *any* decrypted bytes are sent to the receiver.
		for {
			// Figure out how many bytes to read on this iteration.
			readSize := int64(bufferSize)
			final := false
			if left <= bufferSize {
				readSize = left
				final = true
			}

			// Read the (maybe encrypted) bytes from the file.
			n, err := file.Read(buf[:readSize])
			if err != nil {
				return err
			}
			left = left - int64(n)
			hm.Write(buf[:n])
			if final {
				break
			}
		}
		computed := hm.Sum(nil)
		original := buf[:hmacSize]

		// Read the file's version of the HMAC and check it securely
		// against the computed version.
		if _, err := file.Read(original); err != nil {
			return err
		}
		if !hmac.Equal(computed, original) {
			return fmt.Errorf("invalid file HMAC on decryption for file '%s'", fullpath)
		}

		// Go back to the beginning of the file (minus the IV) for
		// decryption.
		if _, err := file.Seek(ivSize, 0); err != nil {
			return fmt.Errorf("couldn't seek back to the beginning of file '%s': %s", fullpath, err)
		}

		// Reset the number of bytes so it only includes the encrypted
		// bytes.
		left = fileInfo.Size() - int64(ivSize+hmacSize)
	}

	// The input buffer, and a temporary buffer for holding decrypted
	// plaintext.
	temp := make([]byte, bufferSize)

	// Set up a framing message to use to send the data.
	m := &Message{
		Type: MessageType_FILE_NEXT.Enum(),
	}

	// Now that the integrity of the data has been verified, if needed, send
	// the data (after decryption, if necessary) to the receiver.
	for {
		// Figure out how many bytes to read on this iteration.
		readSize := int64(bufferSize)
		final := false
		if left <= bufferSize {
			readSize = left
			final = true
			m.Type = MessageType_FILE_LAST.Enum()
		}

		// Read the (maybe encrypted) bytes from the file.
		n, err := file.Read(buf[:readSize])
		if err != nil {
			return err
		}
		left = left - int64(n)

		if hasKeys {
			ctr.XORKeyStream(temp[:n], buf[:n])
			m.Data = temp[:n]
		} else {
			m.Data = buf[:n]
		}

		// Send the decrypted data to the receiver.
		if _, err := ms.WriteMessage(m); err != nil {
			return err
		}
		if final {
			break
		}
	}
	return nil
}
Exemple #25
0
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
	if err := checkPub(&priv.PublicKey); err != nil {
		return nil, err
	}
	k := (priv.N.BitLen() + 7) / 8
	if len(ciphertext) > k ||
		k < hash.Size()*2+2 {
		err = ErrDecryption
		return
	}

	c := new(big.Int).SetBytes(ciphertext)

	m, err := decrypt(random, priv, c)
	if err != nil {
		return
	}

	hash.Write(label)
	lHash := hash.Sum(nil)
	hash.Reset()

	// Converting the plaintext number to bytes will strip any
	// leading zeros so we may have to left pad. We do this unconditionally
	// to avoid leaking timing information. (Although we still probably
	// leak the number of leading zeros. It's not clear that we can do
	// anything about this.)
	em := leftPad(m.Bytes(), k)

	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)

	seed := em[1 : hash.Size()+1]
	db := em[hash.Size()+1:]

	mgf1XOR(seed, hash, db)
	mgf1XOR(db, hash, seed)

	lHash2 := db[0:hash.Size()]

	// We have to validate the plaintext in constant time in order to avoid
	// attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal
	// Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1
	// v2.0. In J. Kilian, editor, Advances in Cryptology.
	lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2)

	// The remainder of the plaintext must be zero or more 0x00, followed
	// by 0x01, followed by the message.
	//   lookingForIndex: 1 iff we are still looking for the 0x01
	//   index: the offset of the first 0x01 byte
	//   invalid: 1 iff we saw a non-zero byte before the 0x01.
	var lookingForIndex, index, invalid int
	lookingForIndex = 1
	rest := db[hash.Size():]

	for i := 0; i < len(rest); i++ {
		equals0 := subtle.ConstantTimeByteEq(rest[i], 0)
		equals1 := subtle.ConstantTimeByteEq(rest[i], 1)
		index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index)
		lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex)
		invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid)
	}

	if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 {
		err = ErrDecryption
		return
	}

	msg = rest[index+1:]
	return
}
Exemple #26
0
func (b *Buffer) PrependHash(h hash.Hash) *Buffer {
	b.SliceBack(h.Size())
	h.Sum(b.Value[:0])
	return b
}
Exemple #27
0
func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
	// See [1], section 9.1.1
	hLen := hash.Size()
	sLen := len(salt)
	emLen := (emBits + 7) / 8

	// 1.  If the length of M is greater than the input limitation for the
	//     hash function (2^61 - 1 octets for SHA-1), output "message too
	//     long" and stop.
	//
	// 2.  Let mHash = Hash(M), an octet string of length hLen.

	if len(mHash) != hLen {
		return nil, errors.New("crypto/rsa: input must be hashed message")
	}

	// 3.  If emLen < hLen + sLen + 2, output "encoding error" and stop.

	if emLen < hLen+sLen+2 {
		return nil, errors.New("crypto/rsa: encoding error")
	}

	em := make([]byte, emLen)
	db := em[:emLen-sLen-hLen-2+1+sLen]
	h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]

	// 4.  Generate a random octet string salt of length sLen; if sLen = 0,
	//     then salt is the empty string.
	//
	// 5.  Let
	//       M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
	//
	//     M' is an octet string of length 8 + hLen + sLen with eight
	//     initial zero octets.
	//
	// 6.  Let H = Hash(M'), an octet string of length hLen.

	var prefix [8]byte

	hash.Write(prefix[:])
	hash.Write(mHash)
	hash.Write(salt)

	h = hash.Sum(h[:0])
	hash.Reset()

	// 7.  Generate an octet string PS consisting of emLen - sLen - hLen - 2
	//     zero octets.  The length of PS may be 0.
	//
	// 8.  Let DB = PS || 0x01 || salt; DB is an octet string of length
	//     emLen - hLen - 1.

	db[emLen-sLen-hLen-2] = 0x01
	copy(db[emLen-sLen-hLen-1:], salt)

	// 9.  Let dbMask = MGF(H, emLen - hLen - 1).
	//
	// 10. Let maskedDB = DB \xor dbMask.

	mgf1XOR(db, hash, h)

	// 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
	//     maskedDB to zero.

	db[0] &= (0xFF >> uint(8*emLen-emBits))

	// 12. Let EM = maskedDB || H || 0xbc.
	em[emLen-1] = 0xBC

	// 13. Output EM.
	return em, nil
}
Exemple #28
0
func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
	// 1.  If the length of M is greater than the input limitation for the
	//     hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
	//     and stop.
	//
	// 2.  Let mHash = Hash(M), an octet string of length hLen.
	hLen := hash.Size()
	if hLen != len(mHash) {
		return ErrVerification
	}

	// 3.  If emLen < hLen + sLen + 2, output "inconsistent" and stop.
	emLen := (emBits + 7) / 8
	if emLen < hLen+sLen+2 {
		return ErrVerification
	}

	// 4.  If the rightmost octet of EM does not have hexadecimal value
	//     0xbc, output "inconsistent" and stop.
	if em[len(em)-1] != 0xBC {
		return ErrVerification
	}

	// 5.  Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
	//     let H be the next hLen octets.
	db := em[:emLen-hLen-1]
	h := em[emLen-hLen-1 : len(em)-1]

	// 6.  If the leftmost 8 * emLen - emBits bits of the leftmost octet in
	//     maskedDB are not all equal to zero, output "inconsistent" and
	//     stop.
	if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
		return ErrVerification
	}

	// 7.  Let dbMask = MGF(H, emLen - hLen - 1).
	//
	// 8.  Let DB = maskedDB \xor dbMask.
	mgf1XOR(db, hash, h)

	// 9.  Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
	//     to zero.
	db[0] &= (0xFF >> uint(8*emLen-emBits))

	if sLen == PSSSaltLengthAuto {
	FindSaltLength:
		for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
			switch db[emLen-hLen-sLen-2] {
			case 1:
				break FindSaltLength
			case 0:
				continue
			default:
				return ErrVerification
			}
		}
		if sLen < 0 {
			return ErrVerification
		}
	} else {
		// 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
		//     or if the octet at position emLen - hLen - sLen - 1 (the leftmost
		//     position is "position 1") does not have hexadecimal value 0x01,
		//     output "inconsistent" and stop.
		for _, e := range db[:emLen-hLen-sLen-2] {
			if e != 0x00 {
				return ErrVerification
			}
		}
		if db[emLen-hLen-sLen-2] != 0x01 {
			return ErrVerification
		}
	}

	// 11.  Let salt be the last sLen octets of DB.
	salt := db[len(db)-sLen:]

	// 12.  Let
	//          M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
	//     M' is an octet string of length 8 + hLen + sLen with eight
	//     initial zero octets.
	//
	// 13. Let H' = Hash(M'), an octet string of length hLen.
	var prefix [8]byte
	hash.Write(prefix[:])
	hash.Write(mHash)
	hash.Write(salt)

	h0 := hash.Sum(nil)

	// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
	if !bytes.Equal(h0, h) {
		return ErrVerification
	}
	return nil
}
Exemple #29
0
func signPayload(payload string, hash hash.Hash) string {
	hash.Write([]byte(payload))
	signature := make([]byte, b64.EncodedLen(hash.Size()))
	b64.Encode(signature, hash.Sum(nil))
	return string(signature)
}
Exemple #30
0
func NewKey(h hash.Hash) ([]byte, error) {
	return Random(h.Size())
}