summaryrefslogtreecommitdiff
path: root/tickets/e438054ed0074cc2b9c85554d2504b38/Maildir/new/1499033705.M790890P475Q1.koom
blob: 34584c8ddf310f7c4c44d6625a9d98cff3cdda0e (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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
Return-Path: <obnam-dev-bounces@obnam.org>
X-Original-To: distix@pieni.net
Delivered-To: distix@pieni.net
Received: from yaffle.pepperfish.net (yaffle.pepperfish.net [88.99.213.221])
	by pieni.net (Postfix) with ESMTPS id 31EF04069D
	for <distix@pieni.net>; Sun,  2 Jul 2017 22:14:56 +0000 (UTC)
Received: from platypus.pepperfish.net (unknown [10.112.101.20])
	by yaffle.pepperfish.net (Postfix) with ESMTP id 0BD6341CC9;
	Sun,  2 Jul 2017 23:14:56 +0100 (BST)
Received: from ip6-localhost.nat ([::1] helo=platypus.pepperfish.net)
	by platypus.pepperfish.net with esmtp (Exim 4.80 #2 (Debian))
	id 1dRn8p-0005Bf-W3; Sun, 02 Jul 2017 23:14:56 +0100
Received: from [10.112.101.21] (helo=inmail2.pepperfish.net)
 by platypus.pepperfish.net with esmtps (Exim 4.80 #2 (Debian))
 id 1dRn8p-0005BS-5m
 for <obnam-dev@obnam.org>; Sun, 02 Jul 2017 23:14:55 +0100
Received: from palant.de ([88.198.212.187])
 by inmail2.pepperfish.net with esmtps
 (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
 (envelope-from <wladimir@palant.de>) id 1dRn8l-0002sz-G1
 for obnam-dev@obnam.org; Sun, 02 Jul 2017 23:14:55 +0100
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=palant.de; 
 s=dkim201610;
 h=Sender:Content-Transfer-Encoding:Content-Type:MIME-Version:
 Date:Message-ID:Subject:From:To;
 bh=9jB012l9uExsMnxvqS532xghyw+gbUdKc0uJXEXhUEU=; b=ogkIn8YJ17qHX+75phP575a7dk
 NlLcXf9fxxWivK6i6kqYX529veVJNMCq4RBy7I4NjdGyoOV9SRsitEWMpvzPsY7D2X4gM1qPMbfBp
 aVIX5nsK/YA6svS8BnmOiS9JXrCh7dmyiOZwJxZABrKUzFiuGv/Igs1GmkJ7ENvcCLiI=;
To: obnam-dev@obnam.org
From: Wladimir Palant <gtiobnam@palant.de>
Message-ID: <2d0a8c01-9f58-1ee7-7e20-53fe65d96718@palant.de>
Date: Mon, 3 Jul 2017 00:14:44 +0200
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
 Thunderbird/52.1.1
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Language: en-US
Content-Transfer-Encoding: 7bit
X-Pepperfish-Transaction: cb00-a5bb-111a-e626
X-Spam-Score: -3.5
X-Spam-Score-int: -34
X-Spam-Bar: ---
X-Scanned-By: pepperfish.net, Sun, 02 Jul 2017 23:14:55 +0100
X-Spam-Report: Content analysis details: (-3.5 points)
 pts rule name              description
 ---- ---------------------- --------------------------------------------------
 -0.5 PPF_USER_AGENT         User-Agent: exists
 -1.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain
 -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
 [score: 0.0000]
 -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
 0.1 DKIM_SIGNED            Message has a DKIM or DK signature,
 not necessarily valid
 -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's
 domain
X-ACL-Warn: message may be spam
X-Scan-Signature: 0efd4b88cb710e1fe5e4a380b3ceab4a
Subject: [rfc] Passphrase-based encryption
X-BeenThere: obnam-dev@obnam.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: Obnam development discussions <obnam-dev-obnam.org>
List-Unsubscribe: <http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/obnam-dev-obnam.org>,
 <mailto:obnam-dev-request@obnam.org?subject=unsubscribe>
List-Archive: <http://listmaster.pepperfish.net/pipermail/obnam-dev-obnam.org>
List-Post: <mailto:obnam-dev@obnam.org>
List-Help: <mailto:obnam-dev-request@obnam.org?subject=help>
List-Subscribe: <http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/obnam-dev-obnam.org>,
 <mailto:obnam-dev-request@obnam.org?subject=subscribe>
Sender: obnam-dev-bounces@obnam.org
Errors-To: obnam-dev-bounces@obnam.org

Hi,

with GPG being great and all that, I'd still prefer having the option to 
use a plain passphrase and AES encryption with obnam. IMHO, this 
approach has two advantages:

* Considerably simpler setup, you merely need to come up with a 
high-entropy passphrase.
* Much easier to back up - you don't need to worry about losing the 
passphrase due to a hard drive crash. If you are afraid of forgetting 
it, then writing it down and keeping somewhere safe will do.

It's particularly that second point which is important to me: if the GPG 
key / passphrase used to encrypt my backup are lost it becomes 
completely useless. With GPG I need to back up the encryption key 
separately, doing so securely tends to be rather complicated.

Sure, passphrases usually won't have the 256 bits of entropy necessary 
to take full advantage of AES-256. However, this doesn't matter much as 
long as they aren't easily guessable and a good (meaning slow) key 
derivation algorithm is used.

I'm currently trying out the following simple plugin to implement 
encryption via passphrase (please don't comment on code quality, this 
hasn't been polished):

> import hashlib
> import os
> 
> from Crypto.Cipher import AES

> class EncryptionPlugin(obnamlib.ObnamPlugin):
>     def enable(self):
>         self.tag = "encaespw"
> 
>         # There doesn't appear to be any "canonical" way to derive an AES key
>         # from a passphrase. There is OpenSSL's enc tool but it uses a very
>         # weak key derivation function (details under
>         # https://security.stackexchange.com/a/29139/4778). So let's just use
>         # PBKDF2 with a high number of iterations.
>         passphrase = os.environ['PASSPHRASE']
>         if not passphrase:
>             raise Exception('No encryption passphrase given')
> 
>         self.key = hashlib.pbkdf2_hmac('sha256', passphrase, 'aes key',
>                                        256 * 1024, dklen=32)
>         self.app.hooks.add_callback('repository-data', self, obnamlib.Hook.LATE_PRIORITY)
> 
> 
>     def filter_read(self, encrypted, repo, toplevel):
>         iv = encrypted[0:16]
>         return AES.new(self.key, AES.MODE_CFB, iv).decrypt(encrypted[16:])
> 
> 
>     def filter_write(self, cleartext, repo, toplevel):
>         iv = os.urandom(16)
>         return iv + AES.new(self.key, AES.MODE_CFB, iv).encrypt(cleartext)

It works nicely and IMHO similar functionality could be added to the 
official distribution. Notes:

* The passphrase is being passed in via an environment variable rather 
than command line parameters. While I am not a Linux expert, it's my 
understanding that this is a more secure approach - the command line can 
be seen by other users on the same computer, environment variables IMHO 
cannot be accessed.

* In my setup, the passphrase is mandatory (I don't want to create an 
unencrypted backup by mistake). In the official encryption plugin, there 
would rather be a command line option like 
--encryption-backend=passphrase to enable passphrase-based encryption. 
Also, the key size doesn't have to be hardcoded at 32 bytes (meaning 
AES-256), there can be an additional option like 
--encryption-algo=aes-128 allowing to specify other key sizes.

* I am currently using a hardcoded salt for PBKDF2. While not 
particularly bad (only relevant if a large number of encrypted obnam 
backups is being accessed by an unauthorized party), this isn't optimal 
either. One solution would be having a random salt for each file, but 
this would require deriving an individual key for each file and degrade 
performance. The other solution would be generating a unique random salt 
for each repository. This would create a single point of failure 
however, if the file storing that random salt gets corrupted the entire 
backup becomes unusable.

* The current encryption plugin will use /dev/random rather than 
/dev/urandom by default. This precaution might be justified when 
generating encryption keys, yet I'm only calling os.urandom() to 
generate the initialization vector. With a new initialization vector 
being generated for each encrypted file, polling /dev/random might be 
too slow here. Also, randomness of initialization vectors isn't as 
critical and doesn't justify such measures IMHO.

Any comments? I can write a patch if the general direction is approved.

regards
Wladimir

_______________________________________________
obnam-dev mailing list
obnam-dev@obnam.org
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/obnam-dev-obnam.org