// Open authenticates and recovers the message secured in the box. func Open(password, box []byte) (msg []byte, ok bool) { if len(box) < (secretbox.Overhead + 2*saltLength) { return } key, ok := recoverKey(password, box[:saltLength]) if !ok { return } ok = false tag := keccakMac(key[:saltLength], box[:saltLength]) if subtle.ConstantTimeCompare(tag, box[saltLength:2*saltLength]) != 1 { return } var sbKey [secretbox.KeySize]byte copy(sbKey[:], key[saltLength:]) msg, ok = secretbox.Open(box[2*saltLength:], &sbKey) secretbox.Zero(sbKey[:]) if !ok { msg = nil return } ok = true return }
// Open authenticates and recovers a message secured with public // key cryptography. func Open(box []byte, priv *[PrivateKeySize]byte) (msg []byte, ok bool) { if len(box) < (2 + PublicKeySize + secretbox.Overhead) { return } else if box[0] != BoxVersion { // Need to convert box to newer version! return } else if box[1] != TypeSingle { return } else if box[2] != CipherDualCurve25519 { return } var pub = new([PublicKeySize]byte) copy(pub[:], box[3:3+PublicKeySize]) var sbox = make([]byte, len(box)-3-PublicKeySize) copy(sbox, box[3+PublicKeySize:]) sk := SharedKey(priv, pub) return secretbox.Open(sbox, sk) }
// Decrypt authenticates and opens the message stored in a box. func Decrypt(key *Key, box *Box) []byte { if key == nil || box == nil { return nil } sbkey := cekdf(key, box.Timestamp) defer zero(sbkey[:]) var tagKey [k512Size]byte copy(tagKey[:], sbkey[k512Size:]) defer zero(tagKey[:]) tag := tagTimestamp(tagKey, box.Timestamp) if subtle.ConstantTimeCompare(tag, box.Tag) != 1 { return nil } msg, ok := secretbox.Open(box.Data, sbkey) if !ok { return nil } return msg }