mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-07 10:56:49 +00:00
use AES from pycryptopp instead of pycrypto, also truncate the keys slightly differently
This commit is contained in:
parent
87e6ccbd4a
commit
0bf5a762a9
@ -24,7 +24,7 @@ except ImportError:
|
||||
install_requires=["zfec >= 1.0.3",
|
||||
"foolscap >= 0.1.6",
|
||||
"simplejson >= 1.4",
|
||||
"pycryptopp >= 0.2.6",
|
||||
"pycryptopp >= 0.2.8",
|
||||
]
|
||||
|
||||
|
||||
|
@ -99,10 +99,11 @@ encrypted child names to rw-URI/ro-URI pairs.
|
||||
|
||||
Each SDMF slot is created with a public/private key pair. The public key is
|
||||
known as the "verification key", while the private key is called the
|
||||
"signature key". The private key is hashed to form the "write key" (an AES
|
||||
symmetric key). The write key is then hashed to form the "read key". The read
|
||||
key is hashed to form the "storage index" (a unique string used as an index
|
||||
to locate stored data).
|
||||
"signature key". The private key is hashed and truncated to 16 bytes to form
|
||||
the "write key" (an AES symmetric key). The write key is then hashed and
|
||||
truncated to form the "read key". The read key is hashed and truncated to
|
||||
form the 16-byte "storage index" (a unique string used as an index to locate
|
||||
stored data).
|
||||
|
||||
The public key is hashed by itself to form the "verification key hash".
|
||||
|
||||
|
@ -11,7 +11,7 @@ from allmydata.interfaces import IMutableFileNode, IDirectoryNode,\
|
||||
from allmydata.util import hashutil
|
||||
from allmydata.util.hashutil import netstring
|
||||
from allmydata.uri import NewDirectoryURI
|
||||
from allmydata.Crypto.Cipher import AES
|
||||
from pycryptopp.cipher.aes import AES
|
||||
|
||||
from allmydata.mutable import MutableFileNode
|
||||
|
||||
@ -79,9 +79,8 @@ class NewDirectoryNode:
|
||||
assert isinstance(rwcap, str)
|
||||
IV = os.urandom(16)
|
||||
key = hashutil.mutable_rwcap_key_hash(IV, self._node.get_writekey())
|
||||
counterstart = "\x00"*16
|
||||
cryptor = AES.new(key=key, mode=AES.MODE_CTR, counterstart=counterstart)
|
||||
crypttext = cryptor.encrypt(rwcap)
|
||||
cryptor = AES(key)
|
||||
crypttext = cryptor.process(rwcap)
|
||||
mac = hashutil.hmac(key, IV + crypttext)
|
||||
assert len(mac) == 32
|
||||
return IV + crypttext + mac
|
||||
@ -93,9 +92,8 @@ class NewDirectoryNode:
|
||||
key = hashutil.mutable_rwcap_key_hash(IV, self._node.get_writekey())
|
||||
if mac != hashutil.hmac(key, IV+crypttext):
|
||||
raise hashutil.IntegrityCheckError("HMAC does not match, crypttext is corrupted")
|
||||
counterstart = "\x00"*16
|
||||
cryptor = AES.new(key=key, mode=AES.MODE_CTR, counterstart=counterstart)
|
||||
plaintext = cryptor.decrypt(crypttext)
|
||||
cryptor = AES(key)
|
||||
plaintext = cryptor.process(crypttext)
|
||||
return plaintext
|
||||
|
||||
def _create_node(self, child_uri):
|
||||
|
@ -10,9 +10,9 @@ from foolscap.eventual import eventually
|
||||
from allmydata.util import idlib, mathutil, hashutil
|
||||
from allmydata.util.assertutil import _assert
|
||||
from allmydata import codec, hashtree, storage, uri
|
||||
from allmydata.Crypto.Cipher import AES
|
||||
from allmydata.interfaces import IDownloadTarget, IDownloader, IFileURI
|
||||
from allmydata.encode import NotEnoughPeersError
|
||||
from pycryptopp.cipher.aes import AES
|
||||
|
||||
class HaveAllPeersError(Exception):
|
||||
# we use this to jump out of the loop
|
||||
@ -31,8 +31,7 @@ class DownloadStopped(Exception):
|
||||
class Output:
|
||||
def __init__(self, downloadable, key, total_length):
|
||||
self.downloadable = downloadable
|
||||
self._decryptor = AES.new(key=key, mode=AES.MODE_CTR,
|
||||
counterstart="\x00"*16)
|
||||
self._decryptor = AES(key)
|
||||
self._crypttext_hasher = hashutil.crypttext_hasher()
|
||||
self._plaintext_hasher = hashutil.plaintext_hasher()
|
||||
self.length = 0
|
||||
@ -59,7 +58,7 @@ class Output:
|
||||
crypttext_leaves = {self._segment_number: ch.digest()}
|
||||
self._crypttext_hash_tree.set_hashes(leaves=crypttext_leaves)
|
||||
|
||||
plaintext = self._decryptor.decrypt(crypttext)
|
||||
plaintext = self._decryptor.process(crypttext)
|
||||
del crypttext
|
||||
|
||||
# now we're back down to 1*segment_size.
|
||||
|
@ -8,10 +8,10 @@ from foolscap.eventual import eventually
|
||||
from allmydata.interfaces import IMutableFileNode, IMutableFileURI
|
||||
from allmydata.util import hashutil, mathutil, idlib, log
|
||||
from allmydata.uri import WriteableSSKFileURI
|
||||
from allmydata.Crypto.Cipher import AES
|
||||
from allmydata import hashtree, codec
|
||||
from allmydata.encode import NotEnoughPeersError
|
||||
from pycryptopp.publickey import rsa
|
||||
from pycryptopp.cipher.aes import AES
|
||||
|
||||
|
||||
class NotMutableError(Exception):
|
||||
@ -400,6 +400,7 @@ class Retrieve:
|
||||
|
||||
if not self._pubkey:
|
||||
fingerprint = hashutil.ssk_pubkey_fingerprint_hash(pubkey_s)
|
||||
assert len(fingerprint) == 32
|
||||
if fingerprint != self._node._fingerprint:
|
||||
raise CorruptShareError(peerid, shnum,
|
||||
"pubkey doesn't match fingerprint")
|
||||
@ -682,8 +683,8 @@ class Retrieve:
|
||||
|
||||
def _decrypt(self, crypttext, IV, seqnum, root_hash):
|
||||
key = hashutil.ssk_readkey_data_hash(IV, self._readkey)
|
||||
decryptor = AES.new(key=key, mode=AES.MODE_CTR, counterstart="\x00"*16)
|
||||
plaintext = decryptor.decrypt(crypttext)
|
||||
decryptor = AES(key)
|
||||
plaintext = decryptor.process(crypttext)
|
||||
# it worked, so record the seqnum and root_hash for next time
|
||||
self._node._populate_seqnum(seqnum)
|
||||
self._node._populate_root_hash(root_hash)
|
||||
@ -1016,8 +1017,8 @@ class Publish:
|
||||
self.log("_encrypt_and_encode")
|
||||
|
||||
key = hashutil.ssk_readkey_data_hash(IV, readkey)
|
||||
enc = AES.new(key=key, mode=AES.MODE_CTR, counterstart="\x00"*16)
|
||||
crypttext = enc.encrypt(newdata)
|
||||
enc = AES(key)
|
||||
crypttext = enc.process(newdata)
|
||||
assert len(crypttext) == len(newdata)
|
||||
|
||||
# now apply FEC
|
||||
@ -1320,13 +1321,13 @@ class MutableFileNode:
|
||||
return d
|
||||
|
||||
def _encrypt_privkey(self, writekey, privkey):
|
||||
enc = AES.new(key=writekey, mode=AES.MODE_CTR, counterstart="\x00"*16)
|
||||
crypttext = enc.encrypt(privkey)
|
||||
enc = AES(writekey)
|
||||
crypttext = enc.process(privkey)
|
||||
return crypttext
|
||||
|
||||
def _decrypt_privkey(self, enc_privkey):
|
||||
enc = AES.new(key=self._writekey, mode=AES.MODE_CTR, counterstart="\x00"*16)
|
||||
privkey = enc.decrypt(enc_privkey)
|
||||
enc = AES(self._writekey)
|
||||
privkey = enc.process(enc_privkey)
|
||||
return privkey
|
||||
|
||||
def _populate(self, stuff):
|
||||
|
@ -13,7 +13,7 @@ from allmydata.util.hashutil import file_renewal_secret_hash, \
|
||||
from allmydata import encode, storage, hashtree, uri
|
||||
from allmydata.util import idlib, mathutil
|
||||
from allmydata.interfaces import IUploadable, IUploader, IEncryptedUploadable
|
||||
from allmydata.Crypto.Cipher import AES
|
||||
from pycryptopp.cipher.aes import AES
|
||||
|
||||
from cStringIO import StringIO
|
||||
|
||||
@ -329,7 +329,7 @@ class EncryptAnUploadable:
|
||||
|
||||
d = self.original.get_encryption_key()
|
||||
def _got(key):
|
||||
e = AES.new(key=key, mode=AES.MODE_CTR, counterstart="\x00"*16)
|
||||
e = AES(key)
|
||||
self._encryptor = e
|
||||
|
||||
storage_index = storage_index_chk_hash(key)
|
||||
@ -390,7 +390,7 @@ class EncryptAnUploadable:
|
||||
chunk = data.pop(0)
|
||||
self._plaintext_hasher.update(chunk)
|
||||
self._update_segment_hash(chunk)
|
||||
cryptdata.append(self._encryptor.encrypt(chunk))
|
||||
cryptdata.append(self._encryptor.process(chunk))
|
||||
del chunk
|
||||
return cryptdata
|
||||
d.addCallback(_got)
|
||||
|
@ -123,9 +123,9 @@ def hmac(tag, data):
|
||||
return h2
|
||||
|
||||
def mutable_rwcap_key_hash(iv, writekey):
|
||||
return tagged_pair_hash("allmydata_mutable_rwcap_key_v1", iv, writekey)
|
||||
return tagged_pair_hash("allmydata_mutable_rwcap_key_v1", iv, writekey)[:16]
|
||||
def ssk_writekey_hash(privkey):
|
||||
return tagged_hash("allmydata_mutable_writekey_v1", privkey)
|
||||
return tagged_hash("allmydata_mutable_writekey_v1", privkey)[:16]
|
||||
def ssk_write_enabler_master_hash(writekey):
|
||||
return tagged_hash("allmydata_mutable_write_enabler_master_v1", writekey)
|
||||
def ssk_write_enabler_hash(writekey, peerid):
|
||||
@ -137,8 +137,8 @@ def ssk_pubkey_fingerprint_hash(pubkey):
|
||||
return tagged_hash("allmydata_mutable_pubkey_v1", pubkey)
|
||||
|
||||
def ssk_readkey_hash(writekey):
|
||||
return tagged_hash("allmydata_mutable_readkey_v1", writekey)
|
||||
return tagged_hash("allmydata_mutable_readkey_v1", writekey)[:16]
|
||||
def ssk_readkey_data_hash(IV, readkey):
|
||||
return tagged_pair_hash("allmydata_mutable_readkey_data_v1", IV, readkey)
|
||||
return tagged_pair_hash("allmydata_mutable_readkey_data_v1", IV, readkey)[:16]
|
||||
def ssk_storage_index_hash(readkey):
|
||||
return tagged_hash("allmydata_mutable_storage_index_v1", readkey)[:16]
|
||||
|
Loading…
x
Reference in New Issue
Block a user