Пример #1
0
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!")
		}
	}
}
Пример #2
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")
}
Пример #3
0
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(";")
}
Пример #4
0
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(";")
}
Пример #5
0
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
}
Пример #6
0
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
}
Пример #7
0
// 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
}
Пример #8
0
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)
}
Пример #9
0
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")
	}
}
Пример #10
0
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
}
Пример #11
0
// 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
}
Пример #12
0
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[:])
}
Пример #13
0
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
}
Пример #14
0
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)
}
Пример #15
0
// 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
}
Пример #16
0
// 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
}
Пример #17
0
// 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
}
Пример #18
0
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[:])
				}
			}
		}
	}
}
Пример #19
0
func GenerateIdentity() *Identity {
	pubKey, priKey, _ := box.GenerateKey(rand.Reader)
	return &Identity{pubKey, priKey}
}
Пример #20
0
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
}
Пример #21
0
func GenerateKeyPair() (publicKey, privateKey *[32]byte, err error) {
	return box.GenerateKey(rand.Reader)
}
Пример #22
0
// 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
}