summaryrefslogtreecommitdiffstats
path: root/custodia/store/encgen.py
blob: 671f152c2a23c931bf86c9b4ec7c2f919a2a59b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Copyright (C) 2015  Custodia Project Contributors - see LICENSE file

from jwcrypto.common import json_decode, json_encode
from jwcrypto.jwe import JWE
from jwcrypto.jwk import JWK

from custodia.store.interface import CSStore, CSStoreError


class EncryptedOverlay(CSStore):

    def __init__(self, config):
        super(EncryptedOverlay, self).__init__(config)

        if 'backing_store' not in config:
            raise ValueError('Missing "backing_store" for Encrypted Store')
        self.store_name = config['backing_store']
        self.store = None

        if 'master_key' not in config:
            raise ValueError('Missing "master_key" for Encrypted Store')

        with open(config['master_key']) as f:
            data = f.read()
            key = json_decode(data)
            self.mkey = JWK(**key)

        self.enc = config.get('master_enctype', 'A256CBC_HS512')

    def get(self, key):
        value = self.store.get(key)
        if value is None:
            return None
        try:
            jwe = JWE()
            jwe.deserialize(value, self.mkey)
            return jwe.payload.decode('utf-8')
        except Exception as err:
            self.logger.error("Error parsing key %s: [%r]" % (key, repr(err)))
            raise CSStoreError('Error occurred while trying to parse key')

    def set(self, key, value, replace=False):
        jwe = JWE(value, json_encode({'alg': 'dir', 'enc': self.enc}))
        jwe.add_recipient(self.mkey)
        cvalue = jwe.serialize(compact=True)
        return self.store.set(key, cvalue, replace)

    def span(self, key):
        return self.store.span(key)

    def list(self, keyfilter=''):
        return self.store.list(keyfilter)

    def cut(self, key):
        return self.store.cut(key)