// Encrypt secures a message with the current timestamp. func Encrypt(key *Key, plaintext []byte) *Box { if key == nil { return nil } now := uint64(time.Now().UnixNano()) sbkey := cekdf(key, now) defer zero(sbkey) sbox, ok := strongbox.Seal(plaintext, sbkey) if !ok { return nil } var tagKey [sha512.Size]byte copy(tagKey[:], sbkey[sha512.Size:]) defer zero(tagKey[:]) tag := tagTimestamp(tagKey, now) return &Box{ Data: sbox, Timestamp: now, Tag: tag, } }
func sealBox(message []byte, peer PublicKey, boxtype byte) *bw { if message == nil { return nil } else if !KeyIsSuitable(nil, peer) { return nil } eph_key, eph_peer, ok := GenerateKey() if !ok { return nil } defer zero(eph_key) skey, ok := ecdh(eph_key, peer) if !ok { return nil } defer zero(skey) packer := newbw([]byte{boxtype}) sbox, ok := strongbox.Seal(message, skey) if !ok { return nil } packer.Write(eph_peer) packer.Write(sbox) return packer }
func boxForPeer(e_priv PrivateKey, peer PublicKey, key strongbox.Key) ([]byte, bool) { shared, ok := ecdh(e_priv, peer) if !ok { return nil, false } defer zero(shared) return strongbox.Seal(key, shared) }
func buildSharedBox(message []byte, peers []PublicKey, btype byte) []byte { if message == nil { return nil } for _, peer := range peers { if peer == nil { return nil } else if !KeyIsSuitable(nil, peer) { return nil } } e_priv, e_pub, ok := GenerateKey() if !ok { return nil } shared, ok := strongbox.GenerateKey() if !ok { return nil } defer zero(shared) packPeers := newbw([]byte{peerList}) packPeers.WriteUint32(uint32(len(peers))) for _, peer := range peers { packPeers.Write(peer) pbox, ok := boxForPeer(e_priv, peer, shared) if !ok { return nil } packPeers.Write(pbox) } plist := packPeers.Bytes() if plist == nil { return nil } packer := newbw([]byte{btype}) packer.Write(e_pub) packer.Write(plist) sbox, ok := strongbox.Seal(message, shared) if !ok { return nil } packer.Write(sbox) return packer.Bytes() }
// Sync secures and writes the vault to disk. func (v *KeyVault) Sync() (err error) { if v == nil { return ErrVaultFailure } var logmeta = Metadata{ "success": "false", } defer v.LogNow("sync", logmeta) v.metadata.WriteLock.Lock() defer v.metadata.WriteLock.Unlock() v.metadata.Locks.Secrets.Lock() v.metadata.Locks.Contexts.Lock() v.metadata.Locks.Revoked.Lock() v.metadata.Locks.Log.Lock() var jv = &vaultJSON{ Secrets: v.secrets, Contexts: v.contexts, AdminContext: v.adminctx, Revoked: v.revoked, Log: v.log, } v.metadata.Locks.Log.Unlock() v.metadata.Locks.Revoked.Unlock() v.metadata.Locks.Contexts.Unlock() v.metadata.Locks.Secrets.Unlock() out, err := json.Marshal(jv) if err != nil { return } out, ok := strongbox.Seal(out, v.metadata.FileKey) if !ok { return ErrInvalidKey } var verBytes = make([]byte, 4) binary.BigEndian.PutUint32(verBytes, v.Version) h := hmac.New(sha512.New, v.metadata.TagKey) h.Write(verBytes) h.Write(v.Salt) var vf = &vaultFile{ Version: v.Version, Salt: v.Salt, Tag: h.Sum(nil), KeyVault: out, } file, err := json.Marshal(vf) if err != nil { return } // Write to a temporary file first; if this succeeds, move the // temporary file to the actual keystore file. tmpFile, err := ioutil.TempFile("", filepath.Base(v.metadata.Filename)) if err != nil { return } tmpFileName := tmpFile.Name() tmpFile.Close() err = ioutil.WriteFile(tmpFileName, file, 0600) if err != nil { os.Remove(tmpFileName) return } err = os.Rename(tmpFileName, v.metadata.Filename) logmeta["success"] = "true" return }