Beispiel #1
0
// 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
}
Beispiel #2
0
// 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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}