Skip to content

Commit b0ca8fa

Browse files
committed
Clean up unicode string typing.
1 parent b351bd5 commit b0ca8fa

3 files changed

Lines changed: 28 additions & 15 deletions

File tree

pyauth/About.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"""Metadata about the program."""
33

44
import sysconfig
5-
import base64
65
import io
76
import pkg_resources
87
import wx

pyauth/AuthenticationStore.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import errno
66
import string
7+
import base64
78
import wx
89
import pyotp
910
from About import GetProgramName, GetVendorName
@@ -61,12 +62,16 @@ def __init__( self, filename, password ):
6162
# algorithm has changed).
6263
self.algorithm = AuthenticationStore.CURRENT_ALGORITHM
6364
self.old_algorithm = self.cfg.Read( '/crypto/algorithm', 'cleartext' )
64-
self.old_password_salt = self.cfg.Read( '/crypto/salt', '' ).encode()
65+
oldsalt = self.cfg.Read( '/crypto/salt', '' )
66+
if self.old_algorithm == 'AES' or self.old_algorithm == 'cleartext':
67+
self.old_password_salt = oldsalt.encode()
68+
else:
69+
self.old_password_salt = base64.urlsafe_b64decode( oldsalt.encode() )
6570
self.decryptor = create_encryption_object( self.old_algorithm, password,
6671
self.old_password_salt )
6772
self.algorithm_changed = self.decryptor.algorithm != self.algorithm
6873
if self.algorithm_changed:
69-
self.password_salt = generate_salt( self.algorithm ).encode()
74+
self.password_salt = generate_salt( self.algorithm )
7075
self.password_changed = True
7176
self.encryptor = create_encryption_object( self.algorithm, password,
7277
self.password_salt )
@@ -146,7 +151,7 @@ def Save( self, force = False ):
146151
for entry in self.entry_list:
147152
entry.Save( self.cfg, "/entries", self.encryptor, force )
148153
if self.password_changed:
149-
self.cfg.Write( '/crypto/salt', self.password_salt )
154+
self.cfg.Write( '/crypto/salt', base64.urlsafe_b64encode( self.password_salt ) )
150155
self.password_changed = False
151156
if self.algorithm_changed:
152157
self.cfg.Write( '/crypto/algorithm', self.algorithm )
@@ -338,7 +343,8 @@ def Load( klass, cfg, entry_group, decryptor ):
338343
sort_index = cfg.ReadInt( 'sort_index' )
339344
provider = cfg.Read( 'provider' )
340345
account = cfg.Read( 'account' )
341-
secret = decryptor.Decrypt( cfg.Read( 'secret' ) )
346+
encrypted_secret = cfg.Read( 'secret' )
347+
secret = decryptor.Decrypt( encrypted_secret )
342348
digits = cfg.ReadInt( 'digits', 6 )
343349
original_label = cfg.Read( 'original_label', '' )
344350
if original_label == '':

pyauth/Encryption.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# -*- coding: utf-8 -*-
2-
"""Encryption for the authentication store."""
2+
"""
3+
Encryption for the authentication store.
4+
5+
Passwords and cleartext are Unicode text strings. Ciphertext is a
6+
Unicode string containing base64-encoded data. The salt used for
7+
key derivation is an unencoded byte string representing raw byte
8+
data (the obsolete AES encryption method uses an unencoded or
9+
Unicode string containing base64 data directly).
10+
"""
311

412
import os
513
import string
@@ -33,7 +41,7 @@ def __init__( self, password = None, salt = None ):
3341
salt = self.storage_key_salt,
3442
iterations = 100000,
3543
backend = self.backend )
36-
self.storage_key = base64.urlsafe_b64encode( kdf.derive( password ) )
44+
self.storage_key = base64.urlsafe_b64encode( kdf.derive( password.encode() ) )
3745

3846
@classmethod
3947
def GenerateSalt( cls ):
@@ -62,7 +70,7 @@ def Encrypt( self, secret ):
6270
cleartext = padder.update( secret.encode() )
6371
cleartext += padder.finalize()
6472
ciphertext = f.encrypt( cleartext.encode() )
65-
return ciphertext
73+
return unicode( ciphertext )
6674

6775
def Decrypt( self, token ):
6876
"""Decrypt a secret using the current key."""
@@ -95,7 +103,7 @@ def __init__( self, password = None, salt = None ):
95103
salt = self.storage_key_salt,
96104
iterations = 10000,
97105
backend = self.backend )
98-
self.storage_key = base64.b64encode( kdf.derive( password ) )
106+
self.storage_key = kdf.derive( password.encode() )
99107

100108
@classmethod
101109
def GenerateSalt( cls ):
@@ -126,7 +134,7 @@ def Decrypt( self, ciphertext ):
126134
b = base64.standard_b64decode( ciphertext )
127135
iv = b[0:self.BLOCK_SIZE]
128136
raw_ciphertext = b[self.BLOCK_SIZE:]
129-
cipher = Cipher( algorithms.AES( base64.b64decode( self.storage_key ) ),
137+
cipher = Cipher( algorithms.AES( self.storage_key ),
130138
modes.CBC( iv ), self.backend )
131139
decryptor = cipher.decryptor()
132140
cleartext = decryptor.update( raw_ciphertext ) + decryptor.finalize()
@@ -150,23 +158,23 @@ def SetPassword( self, new_password, new_salt = None ):
150158
pass
151159

152160
def Encrypt( self, cleartext ):
153-
return cleartext
161+
raise NotImplementedError( "Encryption is not supported by the cleartext algorithm." )
154162

155163
def Decrypt( self, ciphertext ):
156164
return ciphertext
157165

158166
def generate_salt( algorithm_name ):
159167
if algorithm_name == 'FERNET-256':
160-
s = base64.urlsafe_b64encode( Fernet_256.GenerateSalt() )
168+
salt = Fernet_256.GenerateSalt()
161169
else:
162170
raise NotImplementedError( "Algorithm not implemented: " + algorithm_name )
163-
return s
171+
return salt
164172

165173
def create_encryption_object( algorithm_name, password = None, salt = None ):
166174
if algorithm_name == 'FERNET-256':
167-
e = Fernet_256( password.encode(), salt )
175+
e = Fernet_256( password, salt )
168176
elif algorithm_name == 'AES':
169-
e = Old_AES( password.encode(), salt )
177+
e = Old_AES( password, salt )
170178
elif algorithm_name == 'cleartext':
171179
e = Cleartext()
172180
else:

0 commit comments

Comments
 (0)