// Open unlocks and loads the vault from a file. func Open(filename string, key [KeyLen]byte) (vault *KeyVault, err error) { file, err := ioutil.ReadFile(filename) if err != nil { return } var vf vaultFile err = json.Unmarshal(file, &vf) if err != nil { return } var jv vaultJSON out, ok := strongbox.Open(vf.KeyVault, strongbox.Key(key[tagKeyLen:])) if !ok { err = ErrOpenFailure return } else if err = json.Unmarshal(out, &jv); err != nil { return } var verBytes = make([]byte, 4) binary.BigEndian.PutUint32(verBytes, vf.Version) h := hmac.New(sha512.New, key[:tagKeyLen]) h.Write(verBytes) h.Write(vf.Salt) if !hmac.Equal(h.Sum(nil), vf.Tag) { err = ErrOpenFailure return } kek := tkdfKey(key[:]) if kek == nil { err = ErrInvalidKey return } vault = &KeyVault{ Version: vf.Version, Salt: vf.Salt, secrets: jv.Secrets, revoked: jv.Revoked, contexts: jv.Contexts, adminctx: jv.AdminContext, log: jv.Log, metadata: &vaultMetadata{ TagKey: key[:tagKeyLen], Kek: kek, FileKey: key[tagKeyLen:], Filename: filename, WriteLock: new(sync.Mutex), Locks: initLocks(), }, } vault.LogNow("open", nil) return }
// 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 [sha512.Size]byte copy(tagKey[:], sbkey[sha512.Size:]) defer zero(tagKey[:]) tag := tagTimestamp(tagKey, box.Timestamp) if subtle.ConstantTimeCompare(tag, box.Tag) != 1 { return nil } msg, ok := strongbox.Open(box.Data, sbkey) if !ok { return nil } return msg }
func openBox(box []byte, key PrivateKey) (btype byte, message []byte, ok bool) { if box == nil { return 0, nil, false } else if !KeyIsSuitable(key, nil) { return 0, nil, false } btype = box[0] unpacker := newbr(box[1:]) eph_pub := unpacker.Next() sbox := unpacker.Next() shared, ok := ecdh(key, eph_pub) if !ok { return 0, nil, false } message, ok = strongbox.Open(sbox, shared) if !ok { return 0, nil, false } return btype, message, true }
func unpackSharedBox(box []byte, key PrivateKey, public PublicKey) (btype byte, message []byte, ok bool) { if box == nil { return 0, nil, false } else if !KeyIsSuitable(key, public) { return 0, nil, false } btype = box[0] unpacker := newbr(box[1:]) e_pub := unpacker.Next() if e_pub == nil { return 0, nil, false } packedPeers := unpacker.Next() if packedPeers == nil { return 0, nil, false } else if packedPeers[0] != peerList { return 0, nil, false } peerUnpack := newbr(packedPeers[1:]) peerCount, ok := peerUnpack.NextU32() if !ok { return 0, nil, false } var shared []byte = nil defer zero(shared) for i := uint32(0); i < peerCount; i++ { peer := peerUnpack.Next() if peer == nil { return 0, nil, false } sbox := peerUnpack.Next() if sbox == nil { return 0, nil, false } else if !bytes.Equal(peer, public) { continue } skey, ok := ecdh(key, e_pub) if !ok { return 0, nil, false } shared, ok = strongbox.Open(sbox, skey) if !ok { return 0, nil, false } break } if shared == nil { return 0, nil, false } sbox := unpacker.Next() if sbox == nil { return 0, nil, false } message, ok = strongbox.Open(sbox, shared) if !ok { } return btype, message, ok }