func (c *Conn) hcWriteClientHello() error { // Generate a random client nonce. _, err := io.ReadFull(c.cfg.Rand, c.nonceC.initial[:]) if err != nil { return err } // Ensure client nonce does not have last bit set. c.nonceC.initial[23] &= 0xFE // Generate our transient public and private key. Ct, ct, err := box.GenerateKey(c.cfg.Rand) if err != nil { return err } c.curveCt = *Ct c.curvect = *ct // Send client hello b := make([]byte, 65, 81) b[0] = byte(opClientHello) binary.LittleEndian.PutUint32(b[1:5], clientHelloMagic) copy(b[9:41], c.curveCt[:]) copy(b[41:65], c.nonceC.initial[:]) var nonce [24]byte c.nonceC.Next(&nonce) box.Precompute(&c.curveCtS, &c.curveS, &c.curvect) b = box.SealAfterPrecomputation(b, nil, &nonce, &c.curveCtS) return c.conn.WriteFrame(b) }
func (w *encryptWriter) writeBlock(b []byte) int { // Length prefix before the encrypted box so that the // reader knows how much data should be read; eBlock := w.encryptedBlockArray[:len(b)+box.Overhead+2] eBlock[0] = byte(len(b) - 1) // Length prefix inside the encrypted box so that the // reader will be able to check that the unencrypted // length was not tampered with; cBlock := w.clearBlockArray[:len(b)+1] cBlock[0] = byte(len(b) - 1) copy(cBlock[1:], b) // Encrypt the data. eBlock = box.SealAfterPrecomputation(eBlock[:1], cBlock, &w.nonce, &w.sharedKey) w.incrementNonce() _, w.err = w.Writer.Write(eBlock) if w.err != nil { return 0 } return len(b) }
// secWriteLoop copies data from pr into w // doing a nacl seal encryption on the data in the process using shared as the key func secWriteLoop(w io.Writer, pr *io.PipeReader, shared *[32]byte) { var failed bool // check for an error, stops the loop and // closes the pipe with err to signal the writer we failed var check = func(err error) { if err != nil { log.Println("secWriteLoop err:", err) if err2 := pr.CloseWithError(err); err2 != nil { log.Println("CloseWithError failed", err2) } failed = true } } for !failed { // until an error occurs // read the clear message from our pipe msg := make([]byte, 1024) n, err := pr.Read(msg) check(err) // cut of the unused bytes msg = msg[:n] // read 24 bytes of random for our nonce var nonce [24]byte _, err = io.ReadFull(rand.Reader, nonce[:]) check(err) // encrypt and sign our message with the prepended nonce buf := box.SealAfterPrecomputation(nonce[:], msg, &nonce, shared) // copy the sealed message with our passed writer _, err = io.Copy(w, bytes.NewReader(buf)) check(err) } }
func SealStrippedEnvelope(sealed io.Writer, plain io.Reader, ss *[K_SZ]byte, padding byte, msgNumber uint64) error { var ( plainBuf bytes.Buffer cipher []byte nonce [N_SZ]byte ) if padding < 1 { return errors.New("padding must be at lest 1.") } _, err := io.Copy(&plainBuf, plain) if err != nil { return err } paddingBuf := make([]byte, padding) for i := 0; i < int(padding); i++ { paddingBuf[i] = padding } plainBuf.Write(paddingBuf) binary.BigEndian.PutUint64(nonce[N_SZ-LN_SZ:], msgNumber) cipher = box.SealAfterPrecomputation(cipher[:], plainBuf.Bytes(), &nonce, ss) sealed.Write(cipher) return nil }
// Write encrypts and writes len(p) bytes from p to the // underlying data stream. func (w *SecureWriter) Write(p []byte) (int, error) { // validate the incoming message if len(p) == 0 { return 0, errors.New("nothing to write") } else if len(p) > maxMessageSize { return 0, errors.New("message is too large") } // calculate the size of the resulting encrypted message buf := new(bytes.Buffer) bSize := len(p) + 24 + box.Overhead err := binary.Write(buf, binary.LittleEndian, uint32(bSize)) if err != nil { return 0, err } size := buf.Bytes() random := make([]byte, 20) if _, err := rand.Read(random); err != nil { return 0, err } // first 4 bytes of nonce are the encrypted message size // last 20 bytes are random var nonce [24]byte copy(nonce[0:4], size[:]) copy(nonce[4:24], random[:]) // use shared key to encrypt message encrypted := box.SealAfterPrecomputation(nonce[:], p, &nonce, w.sharedKey) w.w.Write(encrypted) return len(p), nil }
func (sw SecureWriter) Write(p []byte) (n int, err error) { // output buffer will contain [nonce + msgLen + encMsg] outputBuffer := new(bytes.Buffer) // Update nonce filling the first 8 bytes with counter // Counter ensures nonce uniqueness and will take hundreds of years to overflow at uint64 binary.BigEndian.PutUint64(sw.nonce[:], sw.counter) sw.counter++ // Write nonce outputBuffer.Write(sw.nonce[:]) ret := box.SealAfterPrecomputation(nil, p, &sw.nonce, &sw.sharedKey) // Preface encrypted message with length of that message binary.Write(outputBuffer, binary.BigEndian, uint64(len(ret))) // copy encrypted message to output buffer n, err = outputBuffer.Write(ret) if err != nil { return n, err } // flush output buffer to underlying writer outputBuffer.WriteTo(sw.writer) // caller only needs to know how many if it's bytes were written, not the encrypted byte count return len(p), nil }
// Write handles encryption and sends the data off with nonce and length in the // header. Do note that any error is unrecoverable if data has been sent, as // the recipient will be unable to understand the stream. func (srwc SecureReadWriteCloser) Write(p []byte) (int, error) { // The structure of a packet for reference is: // [ length uint32 | nonce [24]byte | enc_message []byte ] // Test if the input is too long if len(p) > MaxLength { return 0, ErrOutputTooLong } length := uint32(len(p) + NonceBytes + LengthBytes + box.Overhead) // Prepare the nonce // Using the same nonce twice reduces the difficulty of "guessing" the key, // so that's a big no-no, but while random numbers have a risk for collision, // NaCL docs (http://nacl.cr.yp.to/stream.html) state that, due to the large // nonce size (24 bytes), that randomly generated nonces have negligible risk // of collision. nonce := new([NonceBytes]byte) if _, err := rand.Read(nonce[:]); err != nil { return 0, ErrRandom } // Make a slice with capacity for the entire thing, and the length set to the // length/nonce we'll be copying in message := make([]byte, LengthBytes+NonceBytes, length) binary.BigEndian.PutUint32(message[0:LengthBytes], length) copy(message[LengthBytes:LengthBytes+NonceBytes], nonce[:]) // Encrypt! ret := box.SealAfterPrecomputation(message, p, nonce, srwc.secret) // Write all the things! We just use this as the return value. return srwc.writer.Write(ret) }
// Write encrypts the given data and writes it to the given // Writer interface func (w *SecureWriter) Write(p []byte) (n int, err error) { generateNonce(w.nonce[:]) encrypted := make([]byte, 1024) encrypted = box.SealAfterPrecomputation(nil, p, &w.nonce, &w.SharedKey) n, err = w.Writer.Write(append(w.nonce[:], encrypted...)) return n, err }
// Write encrypts the given bytes and writes them to the underlying writer. // // Upon any write error, the writer should not be used further as the stream // may be in an inconsistent state. func (sw *SecureWriter) Write(p []byte) (int, error) { // create & write the nonce var nonce [24]byte var nonceID = nonce[:8] var nonceRand = nonce[8:] binary.BigEndian.PutUint64(nonceID, uint64(time.Now().UnixNano())) if _, err := rand.Read(nonceRand); err != nil { return 0, err } if _, err := sw.writer.Write(nonce[:]); err != nil { return 0, err } // write the length of the cipher text var ctLen = make([]byte, 4) binary.BigEndian.PutUint32(ctLen, uint32(len(p)+box.Overhead)) if _, err := sw.writer.Write(ctLen); err != nil { return 0, err } // generate & write the cipher text ct := box.SealAfterPrecomputation(nil, p, &nonce, &sw.sharedKey) if _, err := sw.writer.Write(ct); err != nil { return 0, err } return len(p), nil }
// Write encrypts the data in p before writing it to the // underlying writer. func (sw secureWriter) Write(p []byte) (int, error) { // generate random nonce var nonce [nonceLen]byte if _, err := rand.Read(nonce[:]); err != nil { return 0, err } // write the plain-text nonce first, followed by len(p) if _, err := sw.w.Write(nonce[:]); err != nil { return 0, err } // we can assume a max message size of 32 kB, so a uint16 will // be sufficient to hold the length lenp := uint16(len(p)) if err := binary.Write(sw.w, binary.BigEndian, lenp); err != nil { return 0, err } // "clear" the write buffer, encrypt, and send sw.buf = sw.buf[:0] sw.buf = box.SealAfterPrecomputation(sw.buf, p, &nonce, &sw.key) n, err := sw.w.Write(sw.buf) // seal adds box.Overhead additional bytes to p // but we don't want to report that we wrote more bytes than requested if n == len(p)+box.Overhead { n = len(p) } return n, err }
// Write encrypted data func (srw *SecureReadWriter) Write(b []byte) (int, error) { if srw.writer == nil { return 0, fmt.Errorf("writer not set") } if len(b) > maxLength { return 0, fmt.Errorf("data is too big") } buf := make([]byte, sizeLength+nonceLength, len(b)+box.Overhead+sizeLength+nonceLength) size := uint64(len(b)) + nonceLength + box.Overhead binary.PutUvarint(buf[:sizeLength], size) var nonce [nonceLength]byte _, err := rand.Read(nonce[:]) if err != nil { return 0, err } copy(buf[sizeLength:], nonce[:]) buf = box.SealAfterPrecomputation(buf, b, &nonce, srw.shared) _, err = srw.writer.Write(buf) if err != nil { return 0, err } return len(b), nil }
// Write implements io.Writer. func (w SecureWriter) Write(buf []byte) (int, error) { if uint64(len(buf)) > maxMessageSize { return 0, fmt.Errorf("input is too large. Got %d bytes, max: %d", len(buf), maxMessageSize) } // Create a nonce. nonce, err := NewNonce() if err != nil { return 0, err } debugf("Write: nonce\n%s\n", hex.Dump(nonce[:])) // Encrypt the message with the nonce prefix. sealed := box.SealAfterPrecomputation(nonce[:], buf, nonce, w.key) debugf("Write: sealed %d bytes\n%s\n", len(sealed), hex.Dump(sealed)) // Write a fixed header indicating how long the message is. header := uint64(len(sealed)) headerSize := binary.Size(header) if err := binary.Write(w.w, binary.BigEndian, header); err != nil { return headerSize, err } // Write the message. messageSize, err := w.w.Write(sealed) // Return the size of the header and the message. return headerSize + messageSize, err }
// Write satisfies the io.Writer interface. It encrypts the given message and writes the following sequence to the underlying writer: // 1) the fixed length nonce used during encryption // 2) the length of the original message // 3) the encrypted message func (w *SecureWriter) Write(p []byte) (n int, err error) { // make sure we're not trying to send an oversize message if len(p) > MaxMessageBytes { return 0, ErrMessageTooBig } // make sure that the nonce hasn't wrapped around if w.rawNonce == w.iNonce { return 0, ErrTooManyMessages } // write the nonce binary.PutUvarint(w.nonce[:], w.rawNonce) n, err = w.w.Write(w.nonce[:]) if n != len(w.nonce) || err != nil { return 0, err } w.rawNonce++ // and increment it to ensure uniqueness // write the message length err = binary.Write(w.w, binary.BigEndian, uint32(len(p))) if err != nil { return 0, err } // encrypt the message buf := w.buf[0:0] em := box.SealAfterPrecomputation(buf, p, &w.nonce, &w.shared) // and write it n, err = w.w.Write(em) if err != nil { return 0, err } return len(p), nil }
func secureWrite(w io.Writer, p []byte, sharedKey *[32]byte) (n int, err error) { if len(p) > MaxMsgLen { p = p[:MaxMsgLen] } //log.Printf("Writing: %s\n", p) nonce := &[24]byte{} rand.Read(nonce[:]) //log.Printf("Writing nonce: %v\n", nonce) n, err = w.Write(nonce[:]) if err != nil { return } o := box.SealAfterPrecomputation(nil, p, nonce, sharedKey) //log.Printf("Writing encrypted message length: %v\n", uint16(len(o))) err = binary.Write(w, binary.LittleEndian, uint16(len(o))) if err != nil { return } //log.Printf("Writing box: %v\n", o) i, err := w.Write(o) n = n + i if err != nil { return } n = len(p) return }
// Write will encrypt message and write it func (nw NaCLWriter) Write(p []byte) (n int, err error) { // generate a random nonce nonc := (&Nonce).GenerateNonce(*nw.Shared) out := make([]byte, n) b := box.SealAfterPrecomputation(out, p, &nonc, nw.Shared) return nw.Writer.Write(b) }
// Encode encrypts a Message and sends it over a Writer func (enc *Encoder) Encode(msg *Message) error { // rand.Read is guaranteed to read 24 bytes because it calls ReadFull under the covers nonceBytes := make([]byte, 24) _, err := rand.Read(nonceBytes) if err != nil { return err } // We create a fixed array to copy the nonceBytes (there is no way to convert from slice to fixed array without copying) var nonce [24]byte copy(nonce[:], nonceBytes[:]) // box.SealAfterPrecomputation appends the encrypted data to it out and returns it // We pass nonceBytes to the out parameter so we get returned data in the form [nonce][encryptedData] data := box.SealAfterPrecomputation(nonceBytes, msg.Data, &nonce, enc.sharedKey) // Prepend the length to our data so the reader knows how much room to make when reading var length = uint32(len(data)) err = binary.Write(enc.w, binary.BigEndian, length) if err != nil { return nil } _, err = enc.w.Write(data) if err != nil { return err } return nil }
// Write encrypts the message and // writes the result to the underlying data stream. func (s secureWriter) Write(message []byte) (int, error) { // Generate a random nonce nonce, err := generateNonce() if err != nil { return 0, errors.New("Failed to encrypt") } // Prepend the nonce to out out := make([]byte, nonceSize) copy(out[:nonceSize], nonce[:]) // Encrypt the message and prepend to out out = box.SealAfterPrecomputation(out, message[:], nonce, s.sharedKey) // Prepend the length of the message in Uint16 to out's beginning size := make([]byte, 2) binary.BigEndian.PutUint16(size[:], uint16(len(out))) out = append(size, out...) // Write the message decrypted to out ln, err := s.w.Write(out) if err != nil { return 0, err } // Return the length of the message wrote to buff return ln, nil }
func (sw SecureWriter) Write(p []byte) (int, error) { nonce, err := generateNonce() if err != nil { return 0, err } _, err = sw.w.Write(nonce[:]) if err != nil { return 0, err } msgSize := uint32(len(p) + box.Overhead) err = binary.Write(sw.w, binary.LittleEndian, &msgSize) if err != nil { return 0, err } msg := box.SealAfterPrecomputation(nil, p, nonce, sw.sharedKey) n, err := sw.w.Write(msg) if err != nil { return 0, err } n -= box.Overhead return n, nil }
// Write encrypts message and sends to underlying writer. // Write is not concurrent-safe due to keeping sequence for each message. func (s *secureWriter) Write(p []byte) (int, error) { if len(p) == 0 || len(p) > maxMessageSize { return 0, fmt.Errorf("message is empty or too big: %d (max: %d)", len(p), maxMessageSize) } // Create a frame buffer for sending encrypted message. frameSize := headerSize + len(p) + box.Overhead frame := make([]byte, headerSize, frameSize) // Variable nonce is a pointer to a part of the frame buffer. // A new nonce is generated for each message. nonce := (*[nonceSize]byte)(unsafe.Pointer(&frame[noncePos])) s.sequence++ if err := s.generateNonce(nonce); err != nil { return 0, fmt.Errorf("could not generate nonce: %v", err) } // Put length of encrypted message after nonce in the header. binary.BigEndian.PutUint32(frame[lengthPos:], uint32(len(p)+box.Overhead)) // Fill encrypted message which will be box.Overhead bytes longer than // the original. _ = box.SealAfterPrecomputation(frame[headerSize:], p, nonce, &s.sharedKey) n, err := s.writer.Write(frame[:frameSize]) if err != nil { return 0, err } if n != frameSize { return 0, io.ErrShortWrite } return len(p), nil }
func (srv *ConvoService) Get(args *ConvoGetArgs, result *ConvoGetResult) error { log.WithFields(log.Fields{"service": "convo", "rpc": "Get", "round": args.Round, "count": args.Count}).Debug() round, err := srv.getRound(args.Round, convoRoundClosed) if err != nil { return err } nonce := BackwardNonce(args.Round) outgoingOnionSize := srv.PKI.OutgoingOnionOverhead(srv.ServerName) + SizeEncryptedMessage result.Onions = make([][]byte, args.Count) for k := range result.Onions { i := args.Offset + k if v := round.incomingIndex[i]; v > -1 { reply := round.replies[v] onion := box.SealAfterPrecomputation(nil, reply, nonce, round.sharedKeys[i]) result.Onions[k] = onion } if len(result.Onions[k]) != outgoingOnionSize { onion := make([]byte, outgoingOnionSize) rand.Read(onion) result.Onions[k] = onion } } return nil }
// Seals data func (c *BoxConn) seal(b []byte) ([]byte, error) { var nonce [NonceSize]byte n, err := rand.Read(nonce[:]) if err != nil || n != NonceSize { return nil, errors.New("Failed to generate nonce") } return box.SealAfterPrecomputation(nonce[:], b, &nonce, c.sharedSecret), nil }
// Encrypt uses a crypto_box_afternm-equivalent function to encrypt the given data. func Encrypt(data []byte, sharedKey *[SharedKeySize]byte) ([]byte, *[NonceSize]byte, error) { nonce, err := GenerateNonce() if err != nil { return nil, nil, err } return box.SealAfterPrecomputation(nil, data, nonce, sharedKey), nonce, nil }
func (sw *Writer) Write(p []byte) (n int, err error) { out := make([]byte, 0, len(p)+box.Overhead+NonceLength) nonce := sw.generateNonce() out = box.SealAfterPrecomputation(out, p, &nonce, &sw.sharedKey) out = append(out, nonce[:]...) return sw.writer.Write(out) }
// encrypt takes a plaintext message and a key, encrypts the message, // prepend the nonce and returns the resulting ciphertext and any errors. func encrypt(msg []byte, k key) (c []byte, err error) { nonce, err := randomNonce() if err != nil { return nil, err } c = box.SealAfterPrecomputation(c, msg, nonce, k) c = append((*nonce)[:], c...) return c, nil }
// handleConnection is the server side function // handles the public keys exchange as handshake and message serving func handleConnection(conn net.Conn) error { defer conn.Close() // Handshake // Generate server side keys pub, pri, err := box.GenerateKey(rand.Reader) if *pri == *pub || err != nil { return err } // cpubk is the client public key cpubk := make([]byte, 2048) n, err := conn.Read(cpubk) if err != nil { return err } // client public key cpub := &[32]byte{} copy(cpub[:], cpubk[:n]) // send server public key to client _, err = conn.Write(pub[:]) if err != nil { return err } shared := &[32]byte{} // Let's get a bit faster box.Precompute(shared, cpub, pri) // reading message msg := make([]byte, 2048) n, err = conn.Read(msg) if err != nil { fmt.Errorf("could not read message %s", err) return err } // Generate a nonc, to keep it simple we synchronize // nonces between Clietn and Server nonc := &helper.Nonce{} nv := nonc.GenerateNonce(*shared) out := make([]byte, n) // decrypt message dm, ok := box.OpenAfterPrecomputation(out, msg[:n], &nv, shared) if !ok { m := fmt.Sprintf("could not decrypt message %v", msg[:n]) return errors.New(m) } // Send back message encrypted em := box.SealAfterPrecomputation(nil, dm[n:], &nv, shared) _, err = conn.Write(em) if err != nil { return err } return nil }
func (c *Connection) NewKeyPacket(e *fsm.Event) { log.Printf("NewKeyPacket") var err error var secret [32]byte challenge, err := c.NewChallenge() if err != nil { e.Cancel(err) return } h := &Handshake{ Stage: c.local.nextNonce, PublicKey: c.local.perm.PublicKey, } if h.Nonce, err = newNonce(); err != nil { e.Cancel(err) return } secret = computeSharedSecret(&c.local.perm.PrivateKey, &c.remote.temp.PublicKey) // Build the packet buf := new(bytes.Buffer) binary.Write(buf, binary.BigEndian, h.Stage) binary.Write(buf, binary.BigEndian, challenge.Type) binary.Write(buf, binary.BigEndian, challenge.Lookup) binary.Write(buf, binary.BigEndian, challenge.Derivations) binary.Write(buf, binary.BigEndian, challenge.Additional) binary.Write(buf, binary.BigEndian, h.Nonce) binary.Write(buf, binary.BigEndian, h.PublicKey) var out []byte if c.local.temp == nil { c.local.temp, _ = createTempKeyPair() } encryptedTempPubKey := box.SealAfterPrecomputation(out, c.local.temp.PublicKey[:], &h.Nonce, &secret) if debugHandshake { log.Printf("encryptedTempPubKey:\n\tnonce [%x]\n\tsecret [%x]\n\tmyTempPubKey [%x]", h.Nonce, secret, c.local.temp.PublicKey) } binary.Write(buf, binary.BigEndian, encryptedTempPubKey) //handshake, err := NewHandshake(c.local.nextNonce, challenge, c.local, c.remote, &c.passwordHash) n, err := c.conn.WriteToUDP(buf.Bytes(), c.raddr) if err != nil { e.Cancel(err) return } log.Printf("wrote %d to %s", n, c.raddr.String()) }
// Write encrypts b and writes it to the embedded Writer func (s SecureWriter) Write(b []byte) (n int, err error) { msg := box.SealAfterPrecomputation(empty, b, &s.nonce, &s.key) n, err = s.w.Write(msg) if err != nil { return n, err } incrNonce(&s.nonce) return n, nil }
func BenchmarkSealAfterPrecomputation(b *testing.B) { _, myPrivate, _ := box.GenerateKey(rand.Reader) theirPublic, _, _ := box.GenerateKey(rand.Reader) message := make([]byte, 256) nonce := new([24]byte) sharedKey := new([32]byte) box.Precompute(sharedKey, theirPublic, myPrivate) b.ResetTimer() for i := 0; i < b.N; i++ { box.SealAfterPrecomputation(nil, message, nonce, sharedKey) } }
// Write ciphers incoming data `p` and writes it func (w *secureWriter) Write(p []byte) (n int, err error) { nonce := [24]byte{} _, err = rand.Read(nonce[:]) if err != nil { return } out := box.SealAfterPrecomputation(nonce[:], p, &nonce, w.key) return w.w.Write(out) }
// WriteFrame(b) writes the frame to the connection in a length-value-encoded // for so it can be read using ReadFrame on the other side. Returns len(b). func (c *Conn) WriteFrame(b []byte) (int, error) { if len(b) > c.maxFrameSize { return 0, errors.New("write frame too large") } var nonce [24]byte binary.LittleEndian.PutUint64(nonce[:], c.writeNonce) c.writeNonce += 2 i := binary.PutUvarint(c.writeBuf, uint64(box.Overhead+len(b))) buf := box.SealAfterPrecomputation(c.writeBuf[:i], b, &nonce, &c.key) if _, err := c.unencrypted.Write(buf); err != nil { return 0, err } return len(b), nil }