func TestCrypto(t *testing.T) { obfuscationKeyword := "obfuscate" var dummyKey [32]byte for i := 0; i < 100; i++ { senderPublicKey, senderPrivateKey, _ := box.GenerateKey(rand.Reader) recipientPublicKey, recipientPrivateKey, _ := box.GenerateKey(rand.Reader) senderCrypto := New(*senderPublicKey, dummyKey) relayCrypto := New(*recipientPublicKey, *senderPrivateKey) recipientCrypto := New(dummyKey, *recipientPrivateKey) payload := make([]byte, mrand.Intn(250)) rand.Read(payload) //sender encrypted, _ := senderCrypto.Encrypt(payload) obfuscated, _ := senderCrypto.Obfuscate(encrypted, obfuscationKeyword) //relay deobfuscated, _ := senderCrypto.Deobfuscate(obfuscated, obfuscationKeyword) decrypted, _ := relayCrypto.Decrypt(deobfuscated) encrypted, _ = relayCrypto.Encrypt(decrypted) //recepient decrypted, _ = recipientCrypto.Decrypt(encrypted) if !bytes.Equal(payload, decrypted) { t.Fatalf("decrypted payload is not equal to the original!") } } }
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 main() { var rs [256][4][]byte for i := range rs { pk1, _, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } _, sk2, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } var n [24]byte // zero nonce m := make([]byte, i) if _, err := io.ReadFull(rand.Reader, m[:]); err != nil { panic(err) } b := box.Seal(nil, m, &n, pk1, sk2) rs[i][0] = pk1[:] rs[i][1] = sk2[:] rs[i][2] = m rs[i][3] = b } out, err := json.MarshalIndent(rs, "", "") if err != nil { panic(err) } fmt.Print("module.exports = ") fmt.Print(string(out)) fmt.Println(";") }
func main() { var rs [256][5][]byte for i := range rs { pk1, sk1, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } pk2, sk2, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } var out1, out2 [32]byte curve25519.ScalarMult(&out1, sk1, pk2) curve25519.ScalarMult(&out2, sk2, pk1) if out1 != out2 { panic("differ") } rs[i][0] = pk1[:] rs[i][1] = sk1[:] rs[i][2] = pk2[:] rs[i][3] = sk2[:] rs[i][4] = out1[:] } out, err := json.MarshalIndent(rs, "", "") if err != nil { panic(err) } fmt.Print("module.exports = ") fmt.Print(string(out)) fmt.Println(";") }
func (c *Conn) serverHandshake() error { spk, ssk, err := box.GenerateKey(rand.Reader) if err != nil { return err } // key exchange cpk := new([32]byte) _, err = c.conn.Read(cpk[:]) // recv client public key if err != nil { return err } _, err = c.conn.Write(spk[:]) // send server public key to client if err != nil { return err } // end key exchange copy(c.id[:], cpk[:]) c.sr = NewSecureReader(c.conn, ssk, cpk) c.sw = NewSecureWriter(c.conn, ssk, cpk) c.handshakeComplete = true return nil }
func (c *Conn) clientHandshake() error { cpk, csk, err := box.GenerateKey(rand.Reader) if err != nil { return err } // key exchange _, err = c.conn.Write(cpk[:]) // send client public key to server if err != nil { return fmt.Errorf("sending public key %s", err) } spk := new([32]byte) _, err = io.ReadFull(c.conn, spk[:]) // recv server public key if err != nil { return fmt.Errorf("recv public key %s", err) } // end serverKey exchagne copy(c.id[:], spk[:]) c.sr = NewSecureReader(c.conn, csk, spk) c.sw = NewSecureWriter(c.conn, csk, spk) c.handshakeComplete = true return nil }
// GenerateKey generates a new key pair. func GenerateKey() (*KeyPair, error) { var key KeyPair pub, priv, err := box.GenerateKey(rand.Reader) if err != nil { return nil, err } key.Public = PublicKey(*pub) key.Private = *priv return &key, nil }
func (cc *Client) GenUserKeyPair() { pub, prv, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } cc.PubKey = pub[:] cc.PrvKey = prv[:] settings.PutBits("config", "public-key", cc.PubKey) settings.PutBits("config", "private-key", cc.PrvKey) }
func TestGenerateNodeID(t *testing.T) { runtime.GOMAXPROCS(runtime.NumCPU()) pub, _, err := box.GenerateKey(rand.Reader) if err != nil { panic(err) } if id := generateMeshID(pub[:]); !validateMeshID(id) { t.Errorf("Did not generate a valid MeshID") } }
func (cr *Crypto) Encrypt(data []byte) ([]byte, error) { ephemeralPublicKey, ephemeralPrivateKey, err := box.GenerateKey(rand.Reader) if err != nil { return nil, err } ciphertext := box.Seal(nil, data, &cr.nonce, &cr.publicKey, ephemeralPrivateKey) output := make([]byte, 32+len(ciphertext)) copy(output[0:32], ephemeralPublicKey[0:32]) copy(output[32:], ciphertext) return output, nil }
// The connection is lazily established, letting data be included in the handshake. // A subsequent Read() or Write() may fail establishing a connection. func Dial(addr *net.UDPAddr) (c *CurveCPConn, err error) { c = new(CurveCPConn) c.client = new(curveCPClient) c.ephPublicKey, c.ephPrivateKey, err = box.GenerateKey(rand.Reader) if err != nil { return nil, err } // TODO: fetch server and client long-term keys var sPublicKey [32]byte var cPrivateKey [32]byte box.Precompute(&c.client.sharedHelloKey, &sPublicKey, c.ephPrivateKey) box.Precompute(&c.client.sharedVouchKey, &sPublicKey, &cPrivateKey) nonceInt, err := rand.Int(rand.Reader, big.NewInt(1<<48)) // start incrementing at random [0,2^48) if err != nil { return nil, err } c.nonce = nonceInt.Int64() c.conn, err = net.DialUDP("udp", nil, addr) if err != nil { return nil, err } c.sendHello() deadline := 1000 // TODO: add to connection struct connectionTimeout := time.NewTimer(min(deadline, 60*time.Second)) cookies := make(chan bool) go c.cookieReceiver(cookies) for { select { case <-cookies: break case <-time.After(time.Second): // repeat Hello; TODO: fuzz + backoff c.sendHello() case <-connectionTimeout.C: return nil, ConnectionTimeoutError } } go c.clientReactor() return c, nil }
func TestLoadKeys(t *testing.T) { in, err := ioutil.ReadFile(signerFile) checkError(t, err) signer, err = x509.ParsePKCS1PrivateKey(in) checkError(t, err) pub, priv, err := box.GenerateKey(rand.Reader) checkError(t, err) testPriv = make([]byte, 32) testPub = make([]byte, 32) copy(testPriv, priv[:]) copy(testPub, pub[:]) }
func main() { pubkey, privkey, _ := box.GenerateKey(rand.Reader) var publicKey, privateKey []byte publicKey = (*pubkey)[0:32] privateKey = (*privkey)[0:32] m := map[string]string{"publicKey": base64.StdEncoding.EncodeToString(publicKey), "privateKey": base64.StdEncoding.EncodeToString(privateKey)} j, _ := json.Marshal(m) fmt.Printf(string(j)) return }
func main() { armour := flag.Bool("a", false, "armour key") outFile := flag.String("o", "signer", "output file base name") flag.Parse() if *outFile == "" { log.Fatal("no output base filename specified") } pub, priv, err := box.GenerateKey(rand.Reader) if err != nil { log.Fatalf("%v", err) } dumpPrivate(priv, *outFile, *armour) dumpPublic(pub, *outFile, *armour) }
// Serve starts a secure echo server on the given listener. func Serve(l net.Listener) error { myPub, myPriv, err := box.GenerateKey(rand.Reader) if err != nil { return err } for { conn, err := l.Accept() if err != nil { return err } go handle(myPub, myPriv, conn) } return nil }
// Dial generates a private/public key pair, // connects to the server, perform the handshake // and return a reader/writer. func Dial(addr string) (io.ReadWriteCloser, error) { conn, err := net.Dial("tcp", addr) if err != nil { return nil, err } myPub, myPriv, err := box.GenerateKey(rand.Reader) if err != nil { log.Fatal(err) } conn.Write((*myPub)[:]) var theirPub [32]byte conn.Read(theirPub[:]) reader := NewSecureReader(conn, myPriv, &theirPub) writer := NewSecureWriter(conn, myPriv, &theirPub) return secureConn{reader, writer}, nil }
// send encrypts |message| and enqueues it for transmission. func (c *client) send(to *Contact, message *pond.Message) error { messageBytes, err := proto.Marshal(message) if err != nil { return err } if len(messageBytes) > pond.MaxSerializedMessage { return errors.New("message too large") } // All messages are padded to the maximum length. plaintext := make([]byte, pond.MaxSerializedMessage+4) binary.LittleEndian.PutUint32(plaintext, uint32(len(messageBytes))) copy(plaintext[4:], messageBytes) c.randBytes(plaintext[4+len(messageBytes):]) // The message is encrypted to an ephemeral key so that the sending // client can choose not to store it and then cannot decrypt it once // sent. // +---------------------+ +---... // outerNonce | ephemeral DH public | innerNonce | message // (24 bytes) | | (24 bytes) | // +---------------------+ +---.... sealedLen := ephemeralBlockLen + nonceLen + len(plaintext) + box.Overhead sealed := make([]byte, sealedLen) var outerNonce [24]byte c.randBytes(outerNonce[:]) copy(sealed, outerNonce[:]) x := sealed[nonceLen:] public, private, err := box.GenerateKey(c.rand) if err != nil { return err } box.Seal(x[:0], public[:], &outerNonce, &to.theirCurrentDHPublic, &to.lastDHPrivate) x = x[len(public)+box.Overhead:] var innerNonce [24]byte c.randBytes(innerNonce[:]) copy(x, innerNonce[:]) x = x[nonceLen:] box.Seal(x[:0], plaintext, &innerNonce, &to.theirCurrentDHPublic, private) sha := sha256.New() sha.Write(sealed) digest := sha.Sum(nil) sha.Reset() groupSig, err := to.myGroupKey.Sign(c.rand, digest, sha) if err != nil { return err } request := &pond.Request{ Deliver: &pond.Delivery{ To: to.theirIdentityPublic[:], Signature: groupSig, Generation: proto.Uint32(to.generation), Message: sealed, }, } out := &queuedMessage{ request: request, id: *message.Id, to: to.id, server: to.theirServer, message: message, created: time.Unix(*message.Time, 0), } c.enqueue(out) if len(message.Body) > 0 { c.outboxUI.Add(*message.Id, to.name, out.created.Format(shortTimeFormat), indicatorRed) } c.outbox = append(c.outbox, out) return nil }
func (s *server) pump() { rotateMinuteKey := time.NewTicker(30 * time.Second) for { select { case packet := <-s.packetIn: if s.checkHello(packet.buf) { resp := freelist.Packets.Get() resp, scratch := resp[:200], resp[200:] pkey, skey, err := box.GenerateKey(rand.Reader) if err != nil { panic("Ran out of randomness") } // Client short-term public key copy(scratch, packet.buf[40:40+32]) // Server short-term secret key copy(scratch[32:], skey[:]) // minute-key secretbox nonce var nonce [24]byte copy(nonce[:], minuteNoncePrefix) randBytes(nonce[len(minuteNoncePrefix):]) secretbox.Seal(scratch[:64], scratch[:64], &nonce, &s.minuteKey) // Compressed cookie nonce copy(scratch[48:64], nonce[len(minuteNoncePrefix):]) // Server short-term public key copy(scratch[16:48], pkey[:]) var clientKey [32]byte copy(clientKey[:], packet.buf[40:40+32]) // Cookie box nonce copy(nonce[:], cookieNoncePrefix) randBytes(nonce[len(cookieNoncePrefix):]) box.Seal(resp[:56], scratch[16:16+128], &nonce, &clientKey, &s.longTermSecretKey) // Packet header, with extensions swapped. copy(resp, cookieMagic) copy(resp[8:], packet.buf[24:24+16]) copy(resp[24:], packet.buf[8:8+16]) copy(resp[40:], nonce[8:]) s.sock.WriteTo(resp, packet.Addr) freelist.Packets.Put(resp) } else if serverShortTermKey, domain, valid := s.checkInitiate(packet.buf); valid { clientShortTermKey := packet.buf[40 : 40+32] clientLongTermKey := packet.buf[176 : 176+32] if ch, ok := s.conns[string(clientShortTermKey)]; ok { // Forward the Initiate to the conn. Because // checkInitiate replaces the box in the Initiate // packet with its plaintext, and because pump has // done all the crypto verification, conn can // ignore anything not relevant to maintaining // correct stream state. ch <- packet } else if s.listen { // This is a new client initiating. Construct a // conn and wait for someone to Accept() it. c := newConn(s.sock, clientLongTermKey, clientShortTermKey, serverShortTermKey, domain) // TODO: accept timeout or something. s.newConn <- c s.conns[string(clientShortTermKey)] = c.packetIn } } case <-s.stopListen: s.listen = false close(s.newConn) // We hang onto the long term secret key and minute keys // for one full minute key rotation, so that we can still // decode retransmitted Initiate packets for a while. The // rotateMinuteKey case below will take care of final // cleanup. case <-rotateMinuteKey.C: if !s.listen && bytes.Equal(s.minuteKey[:], s.prevMinuteKey[:]) { // At least 30 seconds have passed since we stopped // listening, we can clear the key material and stop // refreshing minute keys. for i := 0; i < len(s.longTermSecretKey); i++ { s.minuteKey[i] = 0 s.prevMinuteKey[i] = 0 s.longTermSecretKey[i] = 0 } rotateMinuteKey.Stop() } else { copy(s.prevMinuteKey[:], s.minuteKey[:]) if s.listen { randBytes(s.minuteKey[:]) } } } } }
func GenerateIdentity() *Identity { pubKey, priKey, _ := box.GenerateKey(rand.Reader) return &Identity{pubKey, priKey} }
func (c *client) send(to *Contact, message *pond.Message) error { messageBytes, err := proto.Marshal(message) if err != nil { return err } if len(messageBytes) > pond.MaxSerializedMessage { return errors.New("message too large") } plaintext := make([]byte, pond.MaxSerializedMessage+4) binary.LittleEndian.PutUint32(plaintext, uint32(len(messageBytes))) copy(plaintext[4:], messageBytes) c.randBytes(plaintext[4+len(messageBytes):]) var innerNonce [24]byte c.randBytes(innerNonce[:]) var sealed, innerSealed []byte sealedLen := nonceLen + len(plaintext) + box.Overhead dhPrivate := &to.lastDHPrivate if to.supportedVersion >= 1 { public, private, err := box.GenerateKey(c.rand) if err != nil { return err } dhPrivate = private var outerNonce [24]byte c.randBytes(outerNonce[:]) sealedLen += ephemeralBlockLen sealed = make([]byte, sealedLen) copy(sealed, outerNonce[:]) box.Seal(sealed[nonceLen:nonceLen], public[:], &outerNonce, &to.theirCurrentDHPublic, &to.lastDHPrivate) innerSealed = sealed[ephemeralBlockLen:] } else { sealed = make([]byte, sealedLen) innerSealed = sealed } copy(innerSealed, innerNonce[:]) box.Seal(innerSealed[nonceLen:nonceLen], plaintext, &innerNonce, &to.theirCurrentDHPublic, dhPrivate) sha := sha256.New() sha.Write(sealed) digest := sha.Sum(nil) sha.Reset() groupSig, err := to.myGroupKey.Sign(c.rand, digest, sha) if err != nil { return err } request := &pond.Request{ Deliver: &pond.Delivery{ To: to.theirIdentityPublic[:], Signature: groupSig, Generation: proto.Uint32(to.generation), Message: sealed, }, } out := &queuedMessage{ request: request, id: *message.Id, to: to.id, server: to.theirServer, message: message, created: time.Unix(*message.Time, 0), } c.enqueue(out) if len(message.Body) > 0 { c.outboxUI.Add(*message.Id, to.name, out.created.Format(shortTimeFormat), indicatorRed) } c.outbox = append(c.outbox, out) return nil }
func GenerateKeyPair() (publicKey, privateKey *[32]byte, err error) { return box.GenerateKey(rand.Reader) }
// processSigningRequest is run on the main goroutine in response to a request // from the network thread to apply a group signature to a message that is just // about to be sent to the destination server. func (c *client) processSigningRequest(sigReq signingRequest) { defer close(sigReq.resultChan) to := c.contacts[sigReq.msg.to] messageBytes, err := proto.Marshal(sigReq.msg.message) if err != nil { c.log.Printf("Failed to sign outgoing message: %s", err) return } if len(messageBytes) > pond.MaxSerializedMessage { c.log.Printf("Failed to sign outgoing message because it's too large") return } // All messages are padded to the maximum length. plaintext := make([]byte, pond.MaxSerializedMessage+4) binary.LittleEndian.PutUint32(plaintext, uint32(len(messageBytes))) copy(plaintext[4:], messageBytes) c.randBytes(plaintext[4+len(messageBytes):]) var sealed []byte if to.ratchet != nil { sealed = to.ratchet.Encrypt(sealed, plaintext) } else { // The message is encrypted to an ephemeral key so that the sending // client can choose not to store it and then cannot decrypt it once // sent. // +---------------------+ +---... // outerNonce | ephemeral DH public | innerNonce | message // (24 bytes) | | (24 bytes) | // +---------------------+ +---.... sealedLen := ephemeralBlockLen + nonceLen + len(plaintext) + box.Overhead sealed = make([]byte, sealedLen) var outerNonce [24]byte c.randBytes(outerNonce[:]) copy(sealed, outerNonce[:]) x := sealed[nonceLen:] public, private, err := box.GenerateKey(c.rand) if err != nil { c.log.Printf("Failed to generate key for outgoing message: %s", err) return } box.Seal(x[:0], public[:], &outerNonce, &to.theirCurrentDHPublic, &to.lastDHPrivate) x = x[len(public)+box.Overhead:] var innerNonce [24]byte c.randBytes(innerNonce[:]) copy(x, innerNonce[:]) x = x[nonceLen:] box.Seal(x[:0], plaintext, &innerNonce, &to.theirCurrentDHPublic, private) } sha := sha256.New() sha.Write(sealed) digest := sha.Sum(nil) sha.Reset() groupSig, err := to.myGroupKey.Sign(c.rand, digest, sha) if err != nil { c.log.Printf("Failed to sign outgoing message: %s", err) return } request := &pond.Request{ Deliver: &pond.Delivery{ To: to.theirIdentityPublic[:], Signature: groupSig, Generation: proto.Uint32(to.generation), Message: sealed, }, } sigReq.resultChan <- request }