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 }
// Open authenticates and decrypts a box produced by Seal and appends the // message to out, which must not overlap box. The output will be Overhead // bytes smaller than box. func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { if len(box) < Overhead { return nil, false } var subKey [32]byte var counter [16]byte setup(&subKey, &counter, nonce, key) // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since // Salsa20 works with 64-byte blocks, we also generate 32 bytes of // keystream as a side effect. var firstBlock [64]byte salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) var poly1305Key [32]byte copy(poly1305Key[:], firstBlock[:]) var tag [poly1305.TagSize]byte copy(tag[:], box) if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { return nil, false } ret, out := sliceForAppend(out, len(box)-Overhead) // We XOR up to 32 bytes of box with the keystream generated from // the first block. box = box[Overhead:] firstMessageBlock := box if len(firstMessageBlock) > 32 { firstMessageBlock = firstMessageBlock[:32] } for i, x := range firstMessageBlock { out[i] = firstBlock[32+i] ^ x } box = box[len(firstMessageBlock):] out = out[len(firstMessageBlock):] // Now decrypt the rest. counter[8] = 1 salsa.XORKeyStream(out, box, &counter, &subKey) return ret, true }
func (s *state) verify(sig, seq, p []byte) bool { if len(sig) != lenAuth { return false } var ( sum [lenAuth]byte key = s.macKey(seq) ) if key == nil { return false } copy(sum[:], sig) return poly1305.Verify(&sum, p, key) }
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 }