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 (noise255) DH(privkey, pubkey []byte) []byte { var dst, in, base [32]byte copy(in[:], privkey) copy(base[:], pubkey) curve25519.ScalarMult(&dst, &in, &base) return dst[:] }
func (kx *KeyExchange) exchange1() error { reply, err := kx.meetingPlace.Exchange(kx.Log, kx.meeting1[:], kx.message1[:], kx.ShutdownChan) if err != nil { return err } var peerDHPublic, encryptedPeerDHPublic [32]byte if len(reply) < len(encryptedPeerDHPublic) { return errors.New("panda: meeting point reply too small") } copy(encryptedPeerDHPublic[:], reply) rijndael.NewCipher(&kx.key).Decrypt(&peerDHPublic, &encryptedPeerDHPublic) curve25519.ScalarMult(&kx.sharedKey, &kx.dhPrivate, &peerDHPublic) paddedLen := kx.meetingPlace.Padding() padded := make([]byte, paddedLen-24 /* nonce */ -secretbox.Overhead) binary.LittleEndian.PutUint32(padded, uint32(len(kx.kxBytes))) copy(padded[4:], kx.kxBytes) if _, err := io.ReadFull(kx.rand, padded[4+len(kx.kxBytes):]); err != nil { return err } var nonce [24]byte if _, err := io.ReadFull(kx.rand, nonce[:]); err != nil { return err } kx.message2 = make([]byte, paddedLen) copy(kx.message2, nonce[:]) secretbox.Seal(kx.message2[24:24], padded, &nonce, &kx.sharedKey) return nil }
func (c *Conn) handshakeClient(handshakeHash hash.Hash, ephemeralPrivate *[32]byte) error { var ephemeralIdentityShared [32]byte curve25519.ScalarMult(&ephemeralIdentityShared, ephemeralPrivate, &c.Peer) digest := handshakeHash.Sum(nil) h := hmac.New(sha256.New, ephemeralIdentityShared[:]) h.Write(serverProofMagic) h.Write(digest) digest = h.Sum(digest[:0]) digestReceived := make([]byte, len(digest)+secretbox.Overhead) n, err := c.read(digestReceived) if err != nil { return err } if n != len(digest) { return shortMessageError } digestReceived = digestReceived[:n] if subtle.ConstantTimeCompare(digest, digestReceived) != 1 { return errors.New("transport: server identity incorrect") } var identityShared [32]byte curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer) handshakeHash.Write(digest) digest = handshakeHash.Sum(digest[:0]) h = hmac.New(sha256.New, identityShared[:]) h.Write(clientProofMagic) h.Write(digest) finalMessage := make([]byte, 32+sha256.Size) copy(finalMessage, c.identityPublic[:]) h.Sum(finalMessage[32:32]) if _, err := c.write(finalMessage); err != nil { return err } return nil }
func (e *curve25519ECDH) GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ([]byte, error) { var priv, pub, secret *[32]byte priv = privKey.(*[32]byte) pub = pubKey.(*[32]byte) secret = new([32]byte) curve25519.ScalarMult(secret, priv, pub) return secret[:], nil }
func (c *Conn) handshakeServer(handshakeHash hash.Hash, theirEphemeralPublic *[32]byte) error { var ephemeralIdentityShared [32]byte curve25519.ScalarMult(&ephemeralIdentityShared, &c.identity, theirEphemeralPublic) digest := handshakeHash.Sum(nil) h := hmac.New(sha256.New, ephemeralIdentityShared[:]) h.Write(serverProofMagic) h.Write(digest) digest = h.Sum(digest[:0]) if _, err := c.write(digest); err != nil { return err } handshakeHash.Write(digest) digest = handshakeHash.Sum(digest[:0]) finalMessage := make([]byte, 32+sha256.Size+secretbox.Overhead) n, err := c.read(finalMessage) if err != nil { return err } if n != 32+sha256.Size { return shortMessageError } finalMessage = finalMessage[:n] copy(c.Peer[:], finalMessage[:32]) var identityShared [32]byte curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer) h = hmac.New(sha256.New, identityShared[:]) h.Write(clientProofMagic) h.Write(digest) digest = h.Sum(digest[:0]) if subtle.ConstantTimeCompare(digest, finalMessage[32:]) != 1 { return errors.New("transport: bad proof from client") } return nil }
// Encrypt acts like append() but appends an encrypted version of msg to out. func (r *Ratchet) Encrypt(out, msg []byte) []byte { if r.ratchet { r.randBytes(r.sendRatchetPrivate[:]) copy(r.sendHeaderKey[:], r.nextSendHeaderKey[:]) var sharedKey, keyMaterial [32]byte curve25519.ScalarMult(&sharedKey, &r.sendRatchetPrivate, &r.recvRatchetPublic) sha := sha256.New() sha.Write(rootKeyUpdateLabel) sha.Write(r.rootKey[:]) sha.Write(sharedKey[:]) if r.v2 { sha.Sum(keyMaterial[:0]) h := hmac.New(sha256.New, keyMaterial[:]) deriveKey(&r.rootKey, rootKeyLabel, h) deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h) deriveKey(&r.sendChainKey, chainKeyLabel, h) } else { sha.Sum(r.rootKey[:0]) h := hmac.New(sha256.New, r.rootKey[:]) deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h) deriveKey(&r.sendChainKey, chainKeyLabel, h) } r.prevSendCount, r.sendCount = r.sendCount, 0 r.ratchet = false } h := hmac.New(sha256.New, r.sendChainKey[:]) var messageKey [32]byte deriveKey(&messageKey, messageKeyLabel, h) deriveKey(&r.sendChainKey, chainKeyStepLabel, h) var sendRatchetPublic [32]byte curve25519.ScalarBaseMult(&sendRatchetPublic, &r.sendRatchetPrivate) var header [headerSize]byte var headerNonce, messageNonce [24]byte r.randBytes(headerNonce[:]) r.randBytes(messageNonce[:]) binary.LittleEndian.PutUint32(header[0:4], r.sendCount) binary.LittleEndian.PutUint32(header[4:8], r.prevSendCount) copy(header[8:], sendRatchetPublic[:]) copy(header[nonceInHeaderOffset:], messageNonce[:]) out = append(out, headerNonce[:]...) out = secretbox.Seal(out, header[:], &headerNonce, &r.sendHeaderKey) r.sendCount++ return secretbox.Seal(out, msg, &messageNonce, &messageKey) }
func (c *Conn) Handshake() error { var ephemeralPrivate, ephemeralPublic, ephemeralShared [32]byte if _, err := io.ReadFull(rand.Reader, ephemeralPrivate[:]); err != nil { return err } curve25519.ScalarBaseMult(&ephemeralPublic, &ephemeralPrivate) if _, err := c.write(ephemeralPublic[:]); err != nil { return err } var theirEphemeralPublic [32]byte if n, err := c.read(theirEphemeralPublic[:]); err != nil || n != len(theirEphemeralPublic) { if err == nil { err = shortMessageError } return err } handshakeHash := sha256.New() if c.isServer { handshakeHash.Write(theirEphemeralPublic[:]) handshakeHash.Write(ephemeralPublic[:]) } else { handshakeHash.Write(ephemeralPublic[:]) handshakeHash.Write(theirEphemeralPublic[:]) } curve25519.ScalarMult(&ephemeralShared, &ephemeralPrivate, &theirEphemeralPublic) c.setupKeys(&ephemeralShared) if c.isServer { return c.handshakeServer(handshakeHash, &theirEphemeralPublic) } return c.handshakeClient(handshakeHash, &ephemeralPrivate) }
// Precompute calculates the shared key between peersPublicKey and privateKey // and writes it to sharedKey. The shared key can be used with // OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing // when using the same pair of keys repeatedly. func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) }
func sharedKey(priv *[32]byte, pub *[32]byte) *[32]byte { var sk = new([32]byte) curve25519.ScalarMult(sk, priv, pub) return sk }
func Before(k *[32]byte, pk, sk *[32]byte) { curve25519.ScalarMult(k, sk, pk) hsalsa20.Core(k, &beforen, k, &sigma) }
func (private Private) SharedSecret(public Public) Secret { var raw CValue curve25519.ScalarMult((*[32]byte)(&raw), (*[32]byte)(&private.private), &public.public) return Secret(raw) }
func (r *Ratchet) Decrypt(ciphertext []byte) ([]byte, error) { msg, err := r.trySavedKeys(ciphertext) if err != nil || msg != nil { return msg, err } sealedHeader := ciphertext[:sealedHeaderSize] sealedMessage := ciphertext[sealedHeaderSize:] var nonce [24]byte copy(nonce[:], sealedHeader) sealedHeader = sealedHeader[len(nonce):] header, ok := secretbox.Open(nil, sealedHeader, &nonce, &r.recvHeaderKey) ok = ok && !isZeroKey(&r.recvHeaderKey) if ok { if len(header) != headerSize { return nil, errors.New("ratchet: incorrect header size") } messageNum := binary.LittleEndian.Uint32(header[:4]) provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, messageNum, r.recvCount) if err != nil { return nil, err } copy(nonce[:], header[nonceInHeaderOffset:]) msg, ok := secretbox.Open(nil, sealedMessage, &nonce, &messageKey) if !ok { return nil, errors.New("ratchet: corrupt message") } copy(r.recvChainKey[:], provisionalChainKey[:]) r.mergeSavedKeys(savedKeys) r.recvCount = messageNum + 1 return msg, nil } header, ok = secretbox.Open(nil, sealedHeader, &nonce, &r.nextRecvHeaderKey) if !ok { return nil, errors.New("ratchet: cannot decrypt") } if len(header) != headerSize { return nil, errors.New("ratchet: incorrect header size") } if r.ratchet { return nil, errors.New("ratchet: received message encrypted to next header key without ratchet flag set") } messageNum := binary.LittleEndian.Uint32(header[:4]) prevMessageCount := binary.LittleEndian.Uint32(header[4:8]) _, _, oldSavedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, prevMessageCount, r.recvCount) if err != nil { return nil, err } var dhPublic, sharedKey, rootKey, chainKey, keyMaterial [32]byte copy(dhPublic[:], header[8:]) curve25519.ScalarMult(&sharedKey, &r.sendRatchetPrivate, &dhPublic) sha := sha256.New() sha.Write(rootKeyUpdateLabel) sha.Write(r.rootKey[:]) sha.Write(sharedKey[:]) var rootKeyHMAC hash.Hash if r.v2 { sha.Sum(keyMaterial[:0]) rootKeyHMAC = hmac.New(sha256.New, keyMaterial[:]) deriveKey(&rootKey, rootKeyLabel, rootKeyHMAC) } else { sha.Sum(rootKey[:0]) rootKeyHMAC = hmac.New(sha256.New, rootKey[:]) } deriveKey(&chainKey, chainKeyLabel, rootKeyHMAC) provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.nextRecvHeaderKey, &chainKey, messageNum, 0) if err != nil { return nil, err } copy(nonce[:], header[nonceInHeaderOffset:]) msg, ok = secretbox.Open(nil, sealedMessage, &nonce, &messageKey) if !ok { return nil, errors.New("ratchet: corrupt message") } copy(r.rootKey[:], rootKey[:]) copy(r.recvChainKey[:], provisionalChainKey[:]) copy(r.recvHeaderKey[:], r.nextRecvHeaderKey[:]) deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, rootKeyHMAC) for i := range r.sendRatchetPrivate { r.sendRatchetPrivate[i] = 0 } copy(r.recvRatchetPublic[:], dhPublic[:]) r.recvCount = messageNum + 1 r.mergeSavedKeys(oldSavedKeys) r.mergeSavedKeys(savedKeys) r.ratchet = true return msg, nil }
// CompleteKeyExchange takes a KeyExchange message from the other party and // establishes the ratchet. func (r *Ratchet) CompleteKeyExchange(kx *pond.KeyExchange, isV2 bool) error { if r.kxPrivate0 == nil { return errors.New("ratchet: handshake already complete") } var public0 [32]byte curve25519.ScalarBaseMult(&public0, r.kxPrivate0) if len(kx.Dh) != len(public0) { return errors.New("ratchet: peer's key exchange is invalid") } if len(kx.Dh1) != len(public0) { return errors.New("ratchet: peer using old-form key exchange") } var amAlice bool switch bytes.Compare(public0[:], kx.Dh) { case -1: amAlice = true case 1: amAlice = false case 0: return errors.New("ratchet: peer echoed our own DH values back") } var theirDH [32]byte copy(theirDH[:], kx.Dh) keyMaterial := make([]byte, 0, 32*5) var sharedKey [32]byte curve25519.ScalarMult(&sharedKey, r.kxPrivate0, &theirDH) keyMaterial = append(keyMaterial, sharedKey[:]...) if amAlice { curve25519.ScalarMult(&sharedKey, r.MyIdentityPrivate, &theirDH) keyMaterial = append(keyMaterial, sharedKey[:]...) curve25519.ScalarMult(&sharedKey, r.kxPrivate0, r.TheirIdentityPublic) keyMaterial = append(keyMaterial, sharedKey[:]...) if !isV2 { keyMaterial = append(keyMaterial, r.MySigningPublic[:]...) keyMaterial = append(keyMaterial, r.TheirSigningPublic[:]...) } } else { curve25519.ScalarMult(&sharedKey, r.kxPrivate0, r.TheirIdentityPublic) keyMaterial = append(keyMaterial, sharedKey[:]...) curve25519.ScalarMult(&sharedKey, r.MyIdentityPrivate, &theirDH) keyMaterial = append(keyMaterial, sharedKey[:]...) if !isV2 { keyMaterial = append(keyMaterial, r.TheirSigningPublic[:]...) keyMaterial = append(keyMaterial, r.MySigningPublic[:]...) } } h := hmac.New(sha256.New, keyMaterial) deriveKey(&r.rootKey, rootKeyLabel, h) if amAlice { deriveKey(&r.recvHeaderKey, headerKeyLabel, h) deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h) deriveKey(&r.nextRecvHeaderKey, nextRecvHeaderKeyLabel, h) deriveKey(&r.recvChainKey, chainKeyLabel, h) copy(r.recvRatchetPublic[:], kx.Dh1) } else { deriveKey(&r.sendHeaderKey, headerKeyLabel, h) deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, h) deriveKey(&r.nextSendHeaderKey, nextRecvHeaderKeyLabel, h) deriveKey(&r.sendChainKey, chainKeyLabel, h) copy(r.sendRatchetPrivate[:], r.kxPrivate1[:]) } r.ratchet = amAlice r.kxPrivate0 = nil r.kxPrivate1 = nil r.v2 = isV2 return nil }