func (s *state) update() { if s.nonce == nil { s.nonce = new([lenNonce]byte) io.ReadFull(rand.Reader, s.nonce[:]) } if s.pktNoncePrefix == nil { s.pktNoncePrefix = new([16]byte) io.ReadFull(rand.Reader, s.pktNoncePrefix[:]) } // generate a local line Key if s.localLineKey == nil { s.localLineKey, _ = generateKey() } // generate mac key base if s.macKeyBase == nil && s.localKey.CanSign() && s.remoteKey.CanEncrypt() { s.macKeyBase = new([lenKey]byte) box.Precompute(s.macKeyBase, s.remoteKey.pub, s.localKey.prv) } // make local token if s.localToken == nil && s.localLineKey != nil { s.localToken = new(cipherset.Token) sha := sha256.Sum256((*s.localLineKey.pub)[:lenToken]) copy((*s.localToken)[:], sha[:lenToken]) } // make remote token if s.remoteToken == nil && s.remoteLineKey != nil { s.remoteToken = new(cipherset.Token) sha := sha256.Sum256((*s.remoteLineKey.pub)[:lenToken]) copy((*s.remoteToken)[:], sha[:lenToken]) } // generate line keys if s.localToken != nil && s.remoteToken != nil && (s.lineEncryptionKey == nil || s.lineDecryptionKey == nil) { var sharedKey [lenKey]byte box.Precompute(&sharedKey, s.remoteLineKey.pub, s.localLineKey.prv) sha := sha256.New() s.lineEncryptionKey = new([lenKey]byte) sha.Write(sharedKey[:]) sha.Write(s.localLineKey.pub[:]) sha.Write(s.remoteLineKey.pub[:]) sha.Sum((*s.lineEncryptionKey)[:0]) sha.Reset() s.lineDecryptionKey = new([lenKey]byte) sha.Write(sharedKey[:]) sha.Write(s.remoteLineKey.pub[:]) sha.Write(s.localLineKey.pub[:]) sha.Sum((*s.lineDecryptionKey)[:0]) } }
func (c *cipher) DecryptMessage(localKey, remoteKey cipherset.Key, p []byte) ([]byte, error) { if len(p) < lenKey+lenNonce+lenAuth { return nil, cipherset.ErrInvalidMessage } var ( ctLen = len(p) - (lenKey + lenNonce + lenAuth) out = make([]byte, ctLen) cs3aLocalKey, _ = localKey.(*key) cs3aRemoteKey, _ = remoteKey.(*key) mac [lenAuth]byte nonce [lenNonce]byte macKey [lenKey]byte agreedKey [lenKey]byte remoteLineKey [lenKey]byte ciphertext []byte ok bool ) if cs3aLocalKey == nil || cs3aRemoteKey == nil { return nil, cipherset.ErrInvalidState } copy(remoteLineKey[:], p[:lenKey]) copy(nonce[:], p[lenKey:lenKey+lenNonce]) copy(mac[:], p[lenKey+lenNonce+ctLen:]) ciphertext = p[lenKey+lenNonce : lenKey+lenNonce+ctLen] { // make macKey box.Precompute(&macKey, cs3aRemoteKey.pub, cs3aLocalKey.prv) var ( sha = sha256.New() ) sha.Write(p[lenKey : lenKey+lenNonce]) sha.Write(macKey[:]) sha.Sum(macKey[:0]) } if !poly1305.Verify(&mac, p[:lenKey+lenNonce+ctLen], &macKey) { return nil, cipherset.ErrInvalidMessage } // make agreedKey box.Precompute(&agreedKey, &remoteLineKey, cs3aLocalKey.prv) // decode BODY out, ok = box.OpenAfterPrecomputation(out[:0], ciphertext, &nonce, &agreedKey) if !ok { return nil, cipherset.ErrInvalidMessage } return out, nil }
func (s *state) EncryptMessage(in []byte) ([]byte, error) { var ( out = bufpool.New().SetLen(lenKey + lenNonce + len(in) + box.Overhead + lenAuth) raw = out.RawBytes() agreedKey [lenKey]byte ctLen int ) if !s.CanEncryptMessage() { panic("unable to encrypt message") } // copy public senderLineKey copy(raw[:lenKey], (*s.localLineKey.pub)[:]) // copy the nonce copy(raw[lenKey:lenKey+lenNonce], s.nonce[:lenNonce]) // make the agreedKey box.Precompute(&agreedKey, s.remoteKey.pub, s.localLineKey.prv) // encrypt p ctLen = len(box.SealAfterPrecomputation(raw[lenKey+lenNonce:lenKey+lenNonce], in, s.nonce, &agreedKey)) // Sign message s.sign(raw[lenKey+lenNonce+ctLen:], s.nonce[:lenNonce], raw[:lenKey+lenNonce+ctLen]) out.SetLen(lenKey + lenNonce + ctLen + lenAuth) return out.Get(nil), nil }
func (c *cipher) DecryptHandshake(localKey cipherset.Key, p []byte) (cipherset.Handshake, error) { if len(p) < lenKey+lenNonce+lenAuth { return nil, cipherset.ErrInvalidMessage } var ( ctLen = len(p) - (lenKey + lenNonce + lenAuth) out = bufpool.New() handshake = &handshake{} cs3aLocalKey, _ = localKey.(*key) at uint32 hasAt bool mac [lenAuth]byte nonce [lenNonce]byte macKey [lenKey]byte agreedKey [lenKey]byte remoteKey [lenKey]byte remoteLineKey [lenKey]byte ciphertext []byte ok bool ) if cs3aLocalKey == nil { return nil, cipherset.ErrInvalidState } copy(remoteLineKey[:], p[:lenKey]) copy(nonce[:], p[lenKey:lenKey+lenNonce]) copy(mac[:], p[lenKey+lenNonce+ctLen:]) ciphertext = p[lenKey+lenNonce : lenKey+lenNonce+ctLen] // make agreedKey box.Precompute(&agreedKey, &remoteLineKey, cs3aLocalKey.prv) // decode BODY outBuf, ok := box.OpenAfterPrecomputation(out.RawBytes(), ciphertext, &nonce, &agreedKey) if !ok { return nil, cipherset.ErrInvalidMessage } out.SetLen(len(outBuf)) { // decode inner inner, err := lob.Decode(out) if err != nil { return nil, cipherset.ErrInvalidMessage } at, hasAt = inner.Header().GetUint32("at") if !hasAt { return nil, cipherset.ErrInvalidMessage } delete(inner.Header().Extra, "at") parts, err := cipherset.PartsFromHeader(inner.Header()) if err != nil { return nil, cipherset.ErrInvalidMessage } if inner.BodyLen() != lenKey { return nil, cipherset.ErrInvalidMessage } inner.Body(remoteKey[:0]) handshake.at = at handshake.key = makeKey(nil, &remoteKey) handshake.lineKey = makeKey(nil, &remoteLineKey) handshake.parts = parts } { // make macKey box.Precompute(&macKey, &remoteKey, cs3aLocalKey.prv) var ( sha = sha256.New() ) sha.Write(p[lenKey : lenKey+lenNonce]) sha.Write(macKey[:]) sha.Sum(macKey[:0]) } if !poly1305.Verify(&mac, p[:lenKey+lenNonce+ctLen], &macKey) { return nil, cipherset.ErrInvalidMessage } return handshake, nil }