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 }
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 }
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 }
/* 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 }
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") }
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 }
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 }
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 }
// 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 }