Beispiel #1
0
func decryptMessageInner(sealed []byte, nonce *[24]byte, from *Contact) ([]byte, bool) {
	if plaintext, ok := box.Open(nil, sealed, nonce, &from.theirLastDHPublic, &from.lastDHPrivate); ok {
		return plaintext, true
	}

	if plaintext, ok := box.Open(nil, sealed, nonce, &from.theirCurrentDHPublic, &from.lastDHPrivate); ok {
		return plaintext, true
	}

	plaintext, ok := box.Open(nil, sealed, nonce, &from.theirLastDHPublic, &from.currentDHPrivate)
	if !ok {
		plaintext, ok = box.Open(nil, sealed, nonce, &from.theirCurrentDHPublic, &from.currentDHPrivate)
		if !ok {
			return nil, false
		}
	}

	// They have clearly received our current DH value. Time to
	// rotate.
	copy(from.lastDHPrivate[:], from.currentDHPrivate[:])
	if _, err := io.ReadFull(rand.Reader, from.currentDHPrivate[:]); err != nil {
		panic(err)
	}
	return plaintext, true
}
Beispiel #2
0
func decryptMessage(sealed []byte, from *Contact) ([]byte, bool) {
	if from.ratchet != nil {
		plaintext, err := from.ratchet.Decrypt(sealed)
		if err != nil {
			return nil, false
		}
		return plaintext, true
	}

	var nonce [24]byte
	if len(sealed) < len(nonce) {
		return nil, false
	}
	copy(nonce[:], sealed)
	sealed = sealed[24:]
	headerLen := ephemeralBlockLen - len(nonce)
	if len(sealed) < headerLen {
		return nil, false
	}

	publicBytes, ok := decryptMessageInner(sealed[:headerLen], &nonce, from)
	if !ok || len(publicBytes) != 32 {
		return nil, false
	}
	var innerNonce [nonceLen]byte
	sealed = sealed[headerLen:]
	copy(innerNonce[:], sealed)
	sealed = sealed[nonceLen:]
	var ephemeralPublicKey [32]byte
	copy(ephemeralPublicKey[:], publicBytes)

	if plaintext, ok := box.Open(nil, sealed, &innerNonce, &ephemeralPublicKey, &from.lastDHPrivate); ok {
		return plaintext, ok
	}

	plaintext, ok := box.Open(nil, sealed, &innerNonce, &ephemeralPublicKey, &from.currentDHPrivate)
	if !ok {
		return nil, false
	}

	// They have clearly received our current DH value. Time to
	// rotate.
	copy(from.lastDHPrivate[:], from.currentDHPrivate[:])
	if _, err := io.ReadFull(rand.Reader, from.currentDHPrivate[:]); err != nil {
		panic(err)
	}
	return plaintext, true
}
Beispiel #3
0
func (d *boxDecoder) encryptedCaveatId(id caveatId) ([]byte, error) {
	if d.key == nil {
		return nil, fmt.Errorf("no public key for caveat id decryption")
	}
	if !bytes.Equal(d.key.Public[:], id.ThirdPartyPublicKey) {
		return nil, fmt.Errorf("public key mismatch")
	}
	var nonce [NonceLen]byte
	if len(id.Nonce) != len(nonce) {
		return nil, fmt.Errorf("bad nonce length")
	}
	copy(nonce[:], id.Nonce)

	var firstPartyPublicKey [KeyLen]byte
	if len(id.FirstPartyPublicKey) != len(firstPartyPublicKey) {
		return nil, fmt.Errorf("bad public key length")
	}
	copy(firstPartyPublicKey[:], id.FirstPartyPublicKey)

	sealed, err := base64.StdEncoding.DecodeString(id.Id)
	if err != nil {
		return nil, fmt.Errorf("cannot base64-decode encrypted caveat id: %v", err)
	}
	out, ok := box.Open(nil, sealed, &nonce, (*[KeyLen]byte)(&firstPartyPublicKey), (*[KeyLen]byte)(&d.key.Private))
	if !ok {
		return nil, fmt.Errorf("decryption of public-key encrypted caveat id %#v failed", id)
	}
	return out, nil
}
Beispiel #4
0
/* Decipher the cipher key to reveal the symmetrical key
 */
func (this *CipherMessage) DecipherKey(ident *Identity) (*[32]byte, error) {
	newError := func(err string) error { return errors.New("Cannot decipher cipher key: " + err) }
	if KeyToString(ident.PublicKey) != this.GetHeader("To") {
		return nil, newError("Wrong identity")
	}
	if ident.PrivateKey == nil {
		return nil, newError("Identity lacks PrivateKey")
	}
	from, err := this.From()
	if err != nil {
		return nil, newError(err.Error())
	}

	// decipher the CipherKey to get the symmetric key
	nonceCipherKey, err := base64.URLEncoding.DecodeString(this.GetHeader("CipherKey"))
	if err != nil {
		return nil, newError("Invalid CipherKey base64")
	}
	if len(nonceCipherKey) != 24+32+box.Overhead { // 24 byte nonce + 32 byte encrypted bytes + overhead bytes
		return nil, newError("Invalid length.")
	}
	var nonce [24]byte
	copy(nonce[:], nonceCipherKey[:24])
	cipherKey := nonceCipherKey[24:]
	var key [32]byte
	_, ok := box.Open(key[:0], cipherKey, &nonce, from.PublicKey, ident.PrivateKey)
	if !ok {
		return nil, newError("Failure")
	}
	return &key, nil
}
Beispiel #5
0
func main() {
	message := []byte("Gophers of the world, unite!")

	alicePublic, alicePrivate, err := box.GenerateKey(rand.Reader)
	if err != nil {
		fmt.Printf("Failed to generate keypair for Alice: %v\n", err)
		return
	}

	bobPublic, bobPrivate, err := box.GenerateKey(rand.Reader)
	if err != nil {
		fmt.Printf("Failed to generate keypair for Bob: %v\n", err)
		return
	}

	encrypted := box.Seal(nil, message, &nonce, bobPublic, alicePrivate)

	decrypted, ok := box.Open(nil, encrypted, &nonce, alicePublic, bobPrivate)
	if !ok {
		fmt.Println("Decryption failed.\n")
		return
	}

	if !bytes.Equal(message, decrypted) {
		fmt.Println("Message recovered failed.\n")
		return
	}

	// Nonce should only be used once.
	updateNonce(&nonce)

	fmt.Println("OK")
}
Beispiel #6
0
func decryptMessage(sealed []byte, nonce *[24]byte, from *Contact) ([]byte, bool) {
	plaintext, ok := decryptMessageInner(sealed, nonce, from)
	if ok {
		return plaintext, true
	}

	// The message might have an ephemeral block, the nonce of which has already been split off.
	headerLen := ephemeralBlockLen - len(nonce)
	if len(sealed) > headerLen {
		publicBytes, ok := decryptMessageInner(sealed[:headerLen], nonce, from)
		if !ok || len(publicBytes) != 32 {
			return nil, false
		}
		var innerNonce [nonceLen]byte
		sealed = sealed[headerLen:]
		copy(innerNonce[:], sealed)
		sealed = sealed[nonceLen:]
		var ephemeralPublicKey [32]byte
		copy(ephemeralPublicKey[:], publicBytes)

		if plaintext, ok := box.Open(nil, sealed, &innerNonce, &ephemeralPublicKey, &from.lastDHPrivate); ok {
			return plaintext, ok
		}

		plaintext, ok := box.Open(nil, sealed, &innerNonce, &ephemeralPublicKey, &from.currentDHPrivate)
		if !ok {
			return nil, false
		}
		// They have clearly received our current DH value. Time to
		// rotate.
		copy(from.lastDHPrivate[:], from.currentDHPrivate[:])
		if _, err := io.ReadFull(rand.Reader, from.currentDHPrivate[:]); err != nil {
			panic(err)
		}
		return plaintext, true
	}

	return nil, false
}
Beispiel #7
0
func (s *server) checkHello(pb []byte) bool {
	if !s.listen || len(pb) != 224 || !bytes.Equal(pb[:8], helloMagic) {
		return false
	}

	var clientKey [32]byte
	copy(clientKey[:], pb[40:40+32])

	var nonce [24]byte
	copy(nonce[:], helloNoncePrefix)
	copy(nonce[len(helloNoncePrefix):], pb[136:136+8])

	var out [64]byte
	_, ok := box.Open(out[:0], pb[144:], &nonce, &clientKey, &s.longTermSecretKey)
	return ok
}
Beispiel #8
0
func (cr *Crypto) Decrypt(data []byte) ([]byte, error) {
	var ephemeralPublicKey [32]byte

	if len(data) < 32 {
		return nil, errors.New("Decrypt: data length < 32")
	}

	copy(ephemeralPublicKey[0:32], data[0:32])
	data = data[32:]

	open, ok := box.Open(nil, data, &cr.nonce, &ephemeralPublicKey, &cr.privateKey)
	if !ok {
		return nil, errors.New("NaCl couldn't decrypt client's payload")
	}
	return open, nil
}
Beispiel #9
0
// If valid == true, pb[176:] is replaced by the plaintext contents of
// the Initiate C'->S' box.
func (s *server) checkInitiate(pb []byte) (serverShortTermKey []byte, domain string, valid bool) {
	valid = false
	if len(pb) < 544 || !bytes.Equal(pb[:8], initiateMagic) {
		return
	}

	// Try to open the cookie.
	var nonce [24]byte
	copy(nonce[:], minuteNoncePrefix)
	copy(nonce[len(minuteNoncePrefix):], pb[72:72+16])

	var cookie [64]byte
	if _, ok := secretbox.Open(cookie[:0], pb[88:168], &nonce, &s.minuteKey); !ok {
		if _, ok = secretbox.Open(cookie[:0], pb[88:168], &nonce, &s.prevMinuteKey); !ok {
			return
		}
	}

	// Check that the cookie and client match
	if !bytes.Equal(cookie[:32], pb[40:40+32]) {
		return
	}

	// Extract server short-term secret key
	var serverKey [32]byte
	serverShortTermKey = serverKey[:]
	copy(serverShortTermKey, cookie[32:])

	// Open the Initiate box using both short-term secret keys.
	copy(nonce[:], initiateNoncePrefix)
	copy(nonce[len(initiateNoncePrefix):], pb[168:168+8])

	var clientShortTermKey [32]byte
	copy(clientShortTermKey[:], pb[40:40+32])

	initiate := make([]byte, len(pb[176:])-box.Overhead)
	if _, ok := box.Open(initiate[:0], pb[176:], &nonce, &clientShortTermKey, &serverKey); !ok {
		return
	}

	if domain = domainToString(initiate[96 : 96+256]); domain == "" {
		return
	}

	// Extract client long-term public key and check the vouch
	// subpacket.
	var clientLongTermKey [32]byte
	copy(clientLongTermKey[:], initiate[:32])

	copy(nonce[:], vouchNoncePrefix)
	copy(nonce[len(vouchNoncePrefix):], initiate[32:32+16])

	var vouch [32]byte
	if _, ok := box.Open(vouch[:0], initiate[48:48+48], &nonce, &clientLongTermKey, &s.longTermSecretKey); !ok {
		return
	}

	if !bytes.Equal(vouch[:], pb[40:40+32]) {
		return
	}

	// The Initiate packet is valid, replace the encrypted box with
	// the plaintext and return.
	copy(pb[176:], initiate)
	for i := len(pb) - box.Overhead; i < len(pb); i++ {
		pb[i] = 0
	}
	valid = true

	return
}