Example #1
0
// CalcSharedSecret does a triple DH from the keypacks to generate the shared secret. myKeys needs to contain private keys, peerKeys only needs public keys
// Sending determines if one is sender or recipient of a message.
func CalcSharedSecret(myKeys, peerKeys *KeyPack, nonce *[NonceSize]byte, sending bool) (sharedSecret [SharedKeySize]byte) {
	preKey := make([]byte, 3*Curve25519KeySize+NonceSize) // three keys plus nonce
	key1, key2, key3 := new(Curve25519Key), new(Curve25519Key), new(Curve25519Key)
	log.Secretf("TemporaryPrivKey: %x\n", *myKeys.TemporaryPrivKey)
	log.Secretf("ConstantPrivKey: %x\n", *myKeys.ConstantPrivKey)
	log.Secretf("TemporaryPubKey: %x\n", *peerKeys.TemporaryPubKey)
	log.Secretf("ConstantPubKey: %x\n", *peerKeys.ConstantPubKey)
	scalarMult(key1, myKeys.TemporaryPrivKey, peerKeys.TemporaryPubKey)
	log.Secretf("Key1: %x\n", *key1)
	scalarMult(key2, myKeys.ConstantPrivKey, peerKeys.TemporaryPubKey)
	scalarMult(key3, myKeys.TemporaryPrivKey, peerKeys.ConstantPubKey)
	preKey = append(preKey, key1[:]...)
	if sending {
		log.Secretf("Key2: %x\n", *key2)
		log.Secretf("Key3: %x\n", *key3)
		preKey = append(preKey, key2[:]...)
		preKey = append(preKey, key3[:]...)
	} else { // Swap for receiver
		log.Secretf("Key2: %x\n", *key3)
		log.Secretf("Key3: %x\n", *key2)
		preKey = append(preKey, key3[:]...)
		preKey = append(preKey, key2[:]...)

	}
	log.Secretf("Nonce: %x\n", *nonce)
	preKey = append(preKey, nonce[:]...)
	return sha512.Sum512(preKey)
}
Example #2
0
// RePad adds the deterministic padding to a message.
func RePad(msg []byte, padKey *[PadKeySize]byte, totalLength int) []byte {
	msgLen := len(msg)
	padLen := totalLength - msgLen
	log.Secretf("RePad Length: %d\n", padLen)
	if padLen <= 0 {
		return msg
	}
	log.Secretf("RePad Key: %x\n", *padKey)
	ret := append(make([]byte, 0), msg[:msgLen-HMACSize]...) // Message body
	ret = append(ret, GenPad(padKey, padLen)...)             // Deterministic padding
	ret = append(ret, msg[msgLen-HMACSize:]...)              // HMAC
	return ret
}
Example #3
0
// DecryptBody decrypts a body and verifies the hmac.
func (bd *DecryptBodyDef) DecryptBody(data []byte) ([]byte, byte, error) {
	var content []byte
	log.Secretf("Shared Secret: %x\n", bd.SharedSecret)
	hmacKey, symmetricKey := CalcKeys(bd.SharedSecret)
	log.Secretf("HMAC Key: %x\n", *hmacKey)
	log.Secretf("Symmetric Key: %x\n", *symmetricKey)
	hmaccalc := hmac.New(sha256.New, hmacKey[:])
	hmaccalc.Write(data[:len(data)-HMACSize])
	hmaccalcSum := hmaccalc.Sum(nil)
	if !hmac.Equal(hmaccalcSum, data[len(data)-HMACSize:]) {
		log.Debugf("Bad HMAC: %x\n", hmaccalcSum)
		return nil, 0, ErrBadHMAC
	}
	blockcipher, err := aes.NewCipher(symmetricKey[:])
	if err != nil {
		return nil, 0, err
	}
	ctr := cipher.NewCTR(blockcipher, bd.IV[:aes.BlockSize])
	// Calculate size of first read. Read one block unless message is too short
	firstRead := aes.BlockSize
	if len(data)-HMACSize < aes.BlockSize {
		firstRead = len(data)
	}
	header := make([]byte, firstRead)
	ctr.XORKeyStream(header, data[:firstRead])
	msgType := header[0]                                             // Decode Message Type
	length := binary.BigEndian.Uint16(header[1:encryptedHeaderSize]) // Decode Message Length
	log.Secretf("Real Length: %d\n", length)
	// Length escapes one block (minus header which is not part of the length)
	if length > aes.BlockSize-encryptedHeaderSize {
		// We have already read aes.BlockSize, but it includes the header
		nlength := length - aes.BlockSize + encryptedHeaderSize
		content = make([]byte, nlength)
		// Decrypt whatever is left
		ctr.XORKeyStream(content, data[aes.BlockSize:aes.BlockSize+nlength])
	}
	// Concat both reads
	content = append(header, content...)
	// Only return after header til end of message
	return content[encryptedHeaderSize : length+encryptedHeaderSize], msgType, nil
}
Example #4
0
// EncryptBody takes data and creates a body out of it.
func (bd *EncryptBodyDef) EncryptBody(data []byte) (*EncryptedBody, error) {
	var detSize int
	dataLen := len(data)
	log.Secretf("Data Length: %d\n", dataLen)
	if dataLen > bd.TotalLength-HMACSize-encryptedHeaderSize || dataLen > BodyMaxLength { // HMac is appended, one byte for type, two for length
		return nil, ErrTooLong
	}

	encryptedHeader := make([]byte, aes.BlockSize)
	log.Secretf("Shared Secret: %x\n", bd.SharedSecret)
	hmacKey, symmetricKey := CalcKeys(bd.SharedSecret)
	log.Secretf("HMAC Key: %x\n", *hmacKey)
	log.Secretf("Symmetric Key: %x\n", *symmetricKey)
	eBody := new(EncryptedBody)
	eBody.Encrypted = make([]byte, dataLen+encryptedHeaderSize)
	blockcipher, err := aes.NewCipher(symmetricKey[:])
	if err != nil {
		return nil, err
	}
	ctr := cipher.NewCTR(blockcipher, bd.IV[:aes.BlockSize])
	log.Secretf("Encrypt IV: %x\n", bd.IV[:aes.BlockSize])
	encryptedHeader[0] = bd.MessageType
	binary.BigEndian.PutUint16(encryptedHeader[1:encryptedHeaderSize], uint16(dataLen)) // Length for data

	if len(data) > aes.BlockSize-encryptedHeaderSize {
		// Multiple blocks. Encrypted header first, then remainder
		copy(encryptedHeader[encryptedHeaderSize:], data[0:aes.BlockSize-encryptedHeaderSize])
		ctr.XORKeyStream(eBody.Encrypted[0:aes.BlockSize], encryptedHeader)
		ctr.XORKeyStream(eBody.Encrypted[aes.BlockSize:], data[aes.BlockSize-encryptedHeaderSize:])
	} else {
		// Short block. Only one encryption
		copy(encryptedHeader[encryptedHeaderSize:], data)
		ctr.XORKeyStream(eBody.Encrypted, encryptedHeader[:len(eBody.Encrypted)])
	}

	hmaccalc := hmac.New(sha256.New, hmacKey[:])
	hmaccalc.Write(eBody.Encrypted)

	detSize = dataLen + encryptedHeaderSize + HMACSize
	if bd.PadToLength-detSize > 0 {
		randomPadKey, err := GenPadKey()
		if err != nil {
			return nil, err
		}
		padlength := bd.PadToLength - detSize
		log.Secretf("Random Pad Key: %x\n", *randomPadKey)
		log.Secretf("Random Pad Length: %d\n", padlength)
		eBody.RandomPadding = GenPad(randomPadKey, padlength)
		detSize = bd.PadToLength
		hmaccalc.Write(eBody.RandomPadding)
	}
	if bd.TotalLength > detSize {
		detPadKey, err := GenPadKey()
		if err != nil {
			return nil, err
		}
		padlength := bd.TotalLength - detSize
		log.Secretf("Deterministic Pad Key: %x\n", *detPadKey)
		log.Secretf("Deterministic Pad Length: %d\n", padlength)

		eBody.PadKey = *detPadKey
		eBody.DeterministicPadding = GenPad(detPadKey, bd.TotalLength-detSize)
		hmaccalc.Write(eBody.DeterministicPadding)
	}
	copy(eBody.HMACSum[:], hmaccalc.Sum(nil))
	return eBody, nil
}