~mtrausch/pymcrypt/trunk

« back to all changes in this revision

Viewing changes to mcrypt.pyx

  • Committer: Michael B. Trausch
  • Date: 2010-12-15 03:41:41 UTC
  • Revision ID: mike@trausch.us-20101215034141-rqno1ukliws8sih3
It builds, it (mostly) works, but it cannot be trusted yet because it corrupts data.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
License: LGPL v3 as published by the Free Software Foundation
4
4
 
5
5
This Python extension module makes it possible to use the mcrypt
6
 
library from within Python.
 
6
library from within Python.  At this point it is best suited for small
 
7
encryption/decryption jobs, as it does not support (for example)
 
8
block-by-block operation just yet.  This is planned for a future
 
9
release.
7
10
 
8
11
This wrapper attempts to expose functionality in a manner useful for
9
12
Python applications.  It does not aim to expose all of the raw
60
63
ALGO_ARCFOUR = b'arcfour'
61
64
ALGO_WAKE = b'wake'
62
65
 
 
66
ALGO_AES = ALGO_RIJNDAEL128
 
67
ALGO_DEFAULT = ALGO_AES
 
68
 
63
69
MODE_CBC = b'cbc'
64
70
MODE_ECB = b'ecb'
65
71
MODE_CFB = b'cfb'
67
73
MODE_nOFB = b'nofb'
68
74
MODE_STREAM = b'stream'
69
75
 
 
76
MODE_DEFAULT = MODE_CBC
 
77
 
70
78
def supports_dynamic_modules():
71
79
    return cmc.mcrypt_module_support_dynamic()
72
80
 
76
84
class McryptWarning(UserWarning):
77
85
    pass
78
86
 
79
 
cdef class mcrypt(object):
80
 
    '''mcrypt([algo[, mode]]) -> mcrypt
81
 
 
82
 
    Creates a new mcrypt object using the specified algorithm and
83
 
    mode; the default algorithm is Rijndael-128 (also known as the
84
 
    Advanced Encryption Standard (AES) in the United States) and the
85
 
    default mode is CBC (cipher-block chaining).  These should be
86
 
    suitable defaults for many applications, but of course you can
87
 
    specify any of the ALGO_* or MODE_* constants should the defaults
88
 
    not be suitable.
89
 
 
90
 
    Also, do not rely on the defaults being the same forever.  If a
91
 
    problem is found with the default algorithm or mode, it may be
92
 
    changed.  Always specify the algorithm and mode explicitly if you
93
 
    depend on it being a particular way, particularly when decrypting.
94
 
 
95
 
    Furthermore, the caller can pass keyword arguments to the
96
 
    constructor:
97
 
 
98
 
      salt: The salt to use with the key derivation algorithm.  It
99
 
      must be at least 8 bytes; salt values smaller than this will be
100
 
      rejected.  A string or Unicode object can be passed in as the
101
 
      salt, in which case it will be converted to a UTF-8 bytestring
102
 
      before use.
103
 
 
104
 
      password: The password to use with the key derivation algorithm.
105
 
      It should be at least 10 bytes, and it can be an arbitrary
106
 
      collection of bytes.  If the password provided is a Python
107
 
      string or Unicode object, it will be converted to a UTF-8
108
 
      bytestring before use.  If the password is less than 10 bytes,
109
 
      it will be rejected unless the keyword argument
110
 
      "allow_unsafe_password" is passed and its value is True.
111
 
 
112
 
      iterations: The number of iterations that the key derivation
113
 
      function will use.  If unspecified, the KDF will be run through
114
 
      10,000 iterations.  Values lower than 1,000 will be rejected
115
 
      unless the keyword argument "allow_unsafe_iterations" is passed
116
 
      and its value is True.
117
 
 
118
 
      iv: The IV (initialization vector), for algorithms that support
119
 
      and/or require one.  The provided IV must be precisely the
120
 
      correct size for the specified algorithm and mode, or a
121
 
      ValueError will be raised.  If an IV is provided and is not
122
 
      necessary, a ValueError will be raised.
123
 
 
124
 
    All other keyword arguments are silently ignored, since it is
125
 
    possible that new arguments may be made available in the
126
 
    future.'''
127
 
 
 
87
class McryptSecurityWarning(McryptWarning):
 
88
    pass
 
89
 
 
90
cdef _s2b(value):
 
91
    '''_s2b(value) -> bytes
 
92
 
 
93
    Returns the value as a bytestring if it is possible to do so.
 
94
    If the value is not a string, it will try to get a string from
 
95
    it before attempting conversion.  This function will always
 
96
    use UTF-8 encoding.'''
 
97
    if isinstance(value, bytes):
 
98
        return value
 
99
    elif isinstance(value, unicode):
 
100
        return value.encode('utf8')
 
101
    elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
 
102
        return value.decode('utf8')
 
103
    else:
 
104
        try:
 
105
            s = str(value)
 
106
            return _s2b(s)
 
107
        except:
 
108
            raise TypeError('value not a string and not convertable')
 
109
    return
 
110
 
 
111
def pbkdf1(password, salt, iterCount, keyLen, **kwargs):
 
112
    supported = { 'md5': { 'mkl': 16, 'class': hashlib.md5 },
 
113
                  'sha1': { 'mkl': 20, 'class': hashlib.sha1 } }
 
114
    if 'algo' not in kwargs:
 
115
        raise ValueError('algo parameter must be md5 or sha1')
 
116
    if kwargs['algo'] == 'md2':
 
117
        raise ValueError('md2 is unsupported')
 
118
    if kwargs['algo'] not in supported:
 
119
        raise ValueError('algo parameter must be md5 or sha1')
 
120
 
 
121
    max_key_len = supported[kwargs['algo']]['mkl']
 
122
    hasher_class = supported[kwargs['algo']]['class']
 
123
 
 
124
    if keyLen == 0:
 
125
        keyLen = max_key_len
 
126
    elif keyLen > max_key_len:
 
127
        msg = 'max key size for algo {0} is {1}'
 
128
        raise ValueError(msg.format(kwargs['algo'], max_key_len))
 
129
 
 
130
    h = hasher_class()
 
131
    h.update(password + salt)
 
132
    out = h.digest()
 
133
 
 
134
    for i in range(iterCount - 1):
 
135
        h = hasher_class()
 
136
        h.update(out)
 
137
        out = h.digest()
 
138
 
 
139
    return out[:keyLen]
 
140
 
 
141
def pbkdf2(password, salt, iterCount, keyLen, **kwargs):
 
142
    cdef unsigned char *out = <unsigned char *>malloc(keyLen)
 
143
    cmc.PKCS5_PBKDF2_HMAC_SHA1(password, len(password),
 
144
                               salt, len(salt),
 
145
                               iterCount, keyLen, out)
 
146
    retval = out[:keyLen]
 
147
    free(<void *>out)
 
148
 
 
149
    return retval
 
150
 
 
151
cdef class _mcrypt_base(object):
 
152
    '''_mcrypt_base([algo[, mode]]) -> _mcrypt_base
 
153
 
 
154
    This is a very basic class and is not intended to be used by
 
155
    Python code.  It contains all of the functionality that can be
 
156
    used by all subclasses, as well as common data fields.  This class
 
157
    does not itself actually perform any encryption or decryption.'''
 
158
 
 
159
    # The underlying (native code) cipherstream object, provided by
 
160
    # the mcrypt library.  It is a pointer to an opaque C struct.
128
161
    cdef cmc.CRYPT_STREAM* _mcStream
129
162
 
130
 
    # Private (inaccessible from Python) attributes
131
163
    cdef bint _initialized
132
 
    cdef char* _algorithm
133
 
    cdef char* _mode
134
 
    cdef int _iterations
135
 
    cdef int _ivSize
 
164
 
 
165
    # One of "encrypt", "decrypt", "none"
 
166
    cdef _encdec_mode
 
167
 
 
168
    # KDF and encryption/decryption parameters
136
169
    cdef bytes _iv
137
 
    cdef int _key_length
 
170
    cdef int _key_len
138
171
    cdef bytes _key
 
172
    cdef int _kdf_iterations
139
173
    cdef bytes _salt
140
 
    cdef bytes _blockSize
141
 
 
142
 
    def __cinit__(self):
143
 
        '''Not used at this time.'''
144
 
        pass
145
 
 
146
 
    def __init__(self, algo = ALGO_RIJNDAEL128, mode = MODE_CBC, **kwargs):
147
 
        '''Initializes an instance of an mcrypt object.
148
 
 
149
 
        See the class docstring for a description of what this does
150
 
        and what parameters it accepts.'''
151
 
        algo = self._s2b(algo) if type(algo) != bytes else algo
152
 
        mode = self._s2b(mode) if type(mode) != bytes else mode
153
 
 
154
 
        self._mcStream = cmc.mcrypt_module_open(algo, NULL, mode, NULL)
155
 
 
156
 
        if self._mcStream is NULL:
157
 
            raise McryptError('mcrypt init failed: ')
 
174
 
 
175
    # object-lifetime static data
 
176
    cdef char* _algorithm
 
177
    cdef char* _mode
 
178
    cdef _avail_key_sizes
 
179
    cdef int _block_size
 
180
    cdef int _iv_len
 
181
 
 
182
    def __init__(self, algo = ALGO_DEFAULT, mode = MODE_DEFAULT):
 
183
        '''Initializes the base object.'''
 
184
        self._open_mcrypt(_s2b(algo), _s2b(mode))
 
185
 
 
186
        try:
 
187
            self._do_init()
 
188
            self._initialized = True
 
189
        except:
 
190
            self._close()
158
191
 
159
192
        self._algorithm = algo
160
193
        self._mode = mode
161
194
 
162
 
        try:
163
 
            self._initParameters(**kwargs)
164
 
        except:
165
 
            self.close()
166
 
            raise
167
 
 
168
 
        self._initIV()
169
 
        self._initialized = True
170
195
        return
171
196
 
172
197
    def __dealloc__(self):
177
202
    def close(self):
178
203
        '''close() -> None
179
204
 
180
 
        Closes the module.  If the constructor succeeded, then you
181
 
        must call this function when you are finished with the mcrypt
182
 
        object.'''
183
 
        if self._mcStream is NULL:
184
 
            raise McryptError('cannot close: not open')
 
205
        Closes the underlying native mcrypt object.'''
 
206
        if self._initialized == False:
 
207
            raise McryptError('not open')
185
208
 
186
 
        cmc.mcrypt_module_close(self._mcStream)
187
 
        self._mcStream = NULL
 
209
        self._close_mcrypt()
188
210
        return
189
211
 
 
212
    def get_allowed_key_sizes(self):
 
213
        '''get_allowed_key_sizes() -> list of int
 
214
        Retrieves the allowed key sizes.'''
 
215
        return self._avail_key_sizes[:]
 
216
 
 
217
    def get_block_size(self):
 
218
        return self._block_size
 
219
 
 
220
    def get_iv(self):
 
221
        '''get_iv() -> bytes
 
222
        Retrieve the current IV block, or None if none.'''
 
223
        if (self._iv_len == 0) or (len(self._iv) == 0):
 
224
            return None
 
225
 
 
226
        return self._iv
 
227
 
 
228
    def get_iv_len(self):
 
229
        '''get_iv_len() -> int
 
230
        Retrieve the IV length, or 0 if no IV needed.'''
 
231
        return self._iv_len
 
232
 
 
233
    def get_key(self):
 
234
        '''get_key() -> bytes
 
235
        Retrieves the encryption key.
 
236
 
 
237
        There is often no need to do this, so doing this is not
 
238
        recommended and will issue a McryptSecurityWarning.  Most
 
239
        likely one will only use this when attempting to debug any
 
240
        interoperability issues (if any arise) having to do with key
 
241
        generation.'''
 
242
        warnings.warn('get_key() is not recommended',
 
243
                      McryptSecurityWarning)
 
244
        klen = len(self._key)
 
245
        if klen == 0 or klen not in self._avail_key_sizes:
 
246
            return None
 
247
        return self._key
 
248
 
 
249
    def get_parameters(self):
 
250
        '''get_parameters() -> dict
 
251
        Retrieves the parameters for repeat or inverse operations.
 
252
 
 
253
        The one parameter that is not present in the dict is the key.
 
254
        The key is assumed to be known and regenerated, and the
 
255
        regenerated key can be coupled with these parameters to, for
 
256
        example, perform a decryption when the present operation is an
 
257
        encryption.'''
 
258
        def _to_hex(bytestr):
 
259
            return ''.join(['{0:02x}'.format(x) for x in bytestr])
 
260
 
 
261
        retval = {}
 
262
 
 
263
        retval['algorithm'] = self._algorithm.decode('utf8')
 
264
        retval['mode'] = self._mode.decode('utf8')
 
265
 
 
266
        if self._iv is None:
 
267
            retval['iv'] = None
 
268
        elif len(self._iv) > 0:
 
269
            retval['iv'] =  _to_hex(self._iv)
 
270
        else:
 
271
            retval['iv'] = None
 
272
 
 
273
        retval['salt'] = _to_hex(self._salt)
 
274
        return(retval)
 
275
 
190
276
    def get_salt(self):
191
 
        if self._salt is None:
192
 
            self.set_salt()
 
277
        '''Retrieve the salt value.'''
193
278
        if len(self._salt) == 0:
194
 
            self.set_salt()
 
279
            return None
195
280
 
196
281
        return self._salt
197
282
 
198
 
    def set_password(self, password, allow_unsafe = False,
199
 
                     kdf = None, **kdfparams):
200
 
        '''set_password(password[, allow_unsafe[, kdf[, *kdfparams]]])
201
 
 
202
 
        Sets the key to be used for encryption or decryption.  If
203
 
        allow_unsafe is True, this function will allow passwords that
204
 
        are shorter than 10 bytes in length.  Presumably, one is using
205
 
        this module because they are interested in providing some sort
206
 
        of security for their data, so this should not be a problem.
207
 
 
208
 
        The caller can specify a custom KDF (key derivation function).
209
 
        A custom-provided KDF has the following function signature:
210
 
 
211
 
          kdf(password, salt, iterCount, keyLen[, kdfparams]) -> key
212
 
 
213
 
        Where the password and salt are bytestrings (<class 'bytes'>
214
 
        in Python 3, or <type 'str'> in Python 2), iterCount is the
215
 
        number of iterations to perform, and keyLen is the length of
216
 
        the key (in BYTES, not BITS).  This can be used if, for
217
 
        example, an application requires compatibility with another
218
 
        application that uses a non-standard KDF.  The KDF must be
219
 
        able to generate a key of the appropriate size for the
220
 
        algorithm/mode pair in use (if it cannot, a call to this
221
 
        function will raise ValueError).
222
 
 
223
 
        If the salt is not set when this function is called, the salt
224
 
        will be set to a random 8-byte (64-bit) value before calling
225
 
        the KDF.  To reproduce the key in the future, the caller must
226
 
        be certain to call .get_salt() and retain that value.
227
 
 
228
 
        By default, this function uses the PBKDF2 function from
229
 
        OpenSSL; also, instance._pbkdf1 is a valid KDF, where
230
 
        "instance" is the name of the instance of an mcrypt object.
231
 
        If any custom keyword arguments need to be passed to the
232
 
        KDF, they can be passed after the kdf parameter.'''
 
283
    # XXX: function-length
 
284
    def set_parameters(self, passwd, salt = None, iv = None,
 
285
                       kdf = None, iters = 10000, klen = 0,
 
286
                       **kwargs):
 
287
        '''set_parameters(passwd[, salt[, iv[, kdf[, iters[, klen]]]]])
 
288
        Set the password for key generation.
 
289
 
 
290
        If salt is not specified, a new salt that is at least 8-bytes
 
291
        long will be generated.  If iv is not specified, a new IV (if
 
292
        one is required) will be generated.  If iters is not
 
293
        specified, a default of 10,000 is used.  If klen (key length)
 
294
        is not specified, the default is to use the largest key length
 
295
        permitted by the current (algorithm, mode) pairs.
 
296
 
 
297
        If kdf is not specified, the default key derivation function
 
298
        (PBKDF2) will be used.  Otherwise, a KDF function must be
 
299
        passed in, and the KDF must look like this:
 
300
 
 
301
            kdf(password, salt, iters, klen, **kwargs) -> key
 
302
 
 
303
        All keyword arguments are passed to the KDF, for extensibility
 
304
        purposes.
 
305
 
 
306
        Note that setting these parameters will rerun the KDF.  This
 
307
        can take a noticable amount of time on a slow system, or even
 
308
        on a fast system when using a very large number of iterations.
 
309
        Since we do not save the password at all, it must be provided
 
310
        every time the user wants to generate the same key.'''
233
311
        if kdf is None:
234
 
            kdf = self._pbkdf2
235
 
 
236
 
        _pass = self._s2b(password)
237
 
 
238
 
        if self._salt is None:
239
 
            self.set_salt()
240
 
        if len(self._salt) == 0:
241
 
            self.set_salt()
242
 
 
243
 
        if len(_pass) < 10 and allow_unsafe == False:
244
 
            raise ValueError('password must be >= 10 bytes long')
245
 
 
246
 
        if self._key_length == 0:
247
 
            self._key_length = self.get_max_key_length()
248
 
 
249
 
        self._key = kdf(_pass, self._salt, self._iterations,
250
 
                        self._key_length, **kdfparams)
251
 
        return
252
 
 
253
 
    def get_max_key_length(self):
254
 
        return cmc.mcrypt_enc_get_key_size(self._mcStream)
255
 
 
256
 
    def get_key(self):
257
 
        '''Returns the encryption key as a bytestring.
258
 
 
259
 
        This function may disappear at some point, as it is not
260
 
        strictly speaking necessary.'''
261
 
        if self._key is None:
262
 
            raise ValueError('key is not set')
263
 
        if len(self._key) < 8:
264
 
            raise ValueError('key is not set')
265
 
 
266
 
        return(self._key)
267
 
 
268
 
    def set_salt(self, salt = None):
269
 
        '''set_salt([salt])
270
 
 
271
 
        Sets the salt value to use with the password when creating the
272
 
        key for encryption or decryption.  If no value is provided, a
273
 
        random 8-byte salt value will be created.  If a value is
274
 
        provided, it must be at least 8 bytes long.  A string or
275
 
        Unicode object can be passed in as the salt, in which case it
276
 
        will be converted to a UTF-8 bytestring before use.'''
277
 
        if salt is None:
278
 
            salt = os.urandom(8)
279
 
        salt = self._s2b(salt)
280
 
 
281
 
        if len(salt) < 8:
282
 
            raise ValueError('Salt is less than min len of 8 bytes')
283
 
 
284
 
        self._salt = salt
285
 
        return
286
 
 
287
 
    def set_iterations(self, iterCount = 10000):
288
 
        '''set_iterations([iterCount])
289
 
 
290
 
        Sets the number of iterations to use for creating the
291
 
        password.  This number is passed to a KDF when creating the
292
 
        key from the password.  If not supplied, the value will be
293
 
        reset to the default of 10,000; otherwise, the value must be
294
 
        greater than 0 (and a warning will be raised if the value is
295
 
        less than 1,000, as this would be considered to be woefully
296
 
        insecure).'''
297
 
        self._iterations = iterCount
298
 
        if iterCount < 1000:
299
 
            msg = 'insecure # of iterations: {}'.format(iterCount)
300
 
            warnings.warn(msg, McryptWarning)
301
 
 
302
 
    def _initIV(self):
303
 
        '''Initializes the IV metadata.'''
304
 
        self._ivSize = cmc.mcrypt_enc_get_iv_size(self._mcStream)
305
 
        return
306
 
 
307
 
    def _initParameters(self, **kwargs):
308
 
        if 'salt' in kwargs:
309
 
            allow_unsafe_salt = False
310
 
 
311
 
            if ('allow_unsafe_salt' in kwargs) and \
312
 
               (kwargs['allow_unsafe_salt'] == True):
313
 
                allow_unsafe_salt = True
314
 
            self.set_salt(kwargs['salt'], allow_unsafe_salt)
315
 
        else:
316
 
            self._salt = self.set_salt(None)
317
 
 
318
 
        if 'password' in kwargs:
319
 
            allow_unsafe_password = False
320
 
 
321
 
            if ('allow_unsafe_password' in kwargs) and \
322
 
               (kwargs['allow_unsafe_password'] == True):
323
 
                allow_unsafe_password = True
324
 
            self.set_password(kwargs['password'],
325
 
                              allow_unsafe_password)
326
 
        else:
327
 
            self._key = None
328
 
 
329
 
        if 'iterations' in kwargs:
330
 
            allow_unsafe_iterations = False
331
 
 
332
 
            if ('allow_unsafe_iterations' in kwargs) and \
333
 
               (kwargs['allow_unsafe_iterations'] == True):
334
 
                allow_unsafe_iterations = True
335
 
            self.set_iterations(kwargs['iterations'],
336
 
                                allow_unsafe_iterations)
337
 
        else:
338
 
            self._iterations = 10000
339
 
 
340
 
        if 'iv' in kwargs:
341
 
            self.set_iv(kwargs['iv'])
342
 
 
343
 
        return
344
 
 
345
 
    def _pbkdf2(self, password, salt, iterCount, keyLen, **kwargs):
346
 
        cdef unsigned char *out = <unsigned char *>malloc(keyLen)
347
 
        cmc.PKCS5_PBKDF2_HMAC_SHA1(password, len(password),
348
 
                                   salt, len(salt),
349
 
                                   iterCount, keyLen, out)
350
 
        retval = out[:keyLen]
351
 
        free(<void *>out)
352
 
 
353
 
        return retval
354
 
 
355
 
    # XXX: function length
356
 
    def _pbkdf1(self, password, salt, iterCount, keyLen, **kwargs):
357
 
        supported = { 'md5': { 'mkl': 16, 'class': hashlib.md5 },
358
 
                      'sha1': { 'mkl': 20, 'class': hashlib.sha1 } }
359
 
        if 'algo' not in kwargs:
360
 
            raise ValueError('algo parameter must be md5 or sha1')
361
 
        if kwargs['algo'] == 'md2':
362
 
            raise ValueError('md2 is unsupported')
363
 
        if kwargs['algo'] not in supported:
364
 
            raise ValueError('algo parameter must be md5 or sha1')
365
 
 
366
 
        max_key_len = supported[kwargs['algo']]['mkl']
367
 
        hasher_class = supported[kwargs['algo']]['class']
368
 
 
369
 
        if keyLen == 0:
370
 
            keyLen = max_key_len
371
 
        elif keyLen > max_key_len:
372
 
            msg = 'max key size for algo {} is {}'
373
 
            raise ValueError(msg.format(kwargs['algo'], max_key_len))
374
 
 
375
 
        h = hasher_class()
376
 
        h.update(password + salt)
377
 
        out = h.digest()
378
 
 
379
 
        for i in range(iterCount - 1):
380
 
            h = hasher_class()
381
 
            h.update(out)
382
 
            out = h.digest()
383
 
 
384
 
        return out[:keyLen]
385
 
 
386
 
    def _s2b(self, value):
387
 
        '''_s2b(value) -> bytes
388
 
 
389
 
        Returns the value as a bytestring if it is possible to do so.
390
 
        If the value is not a string, it will try to get a string from
391
 
        it before attempting conversion.  This function will always
392
 
        use UTF-8 encoding.'''
393
 
        if isinstance(value, bytes):
394
 
            return value
395
 
        elif isinstance(value, unicode):
396
 
            return value.encode('utf8')
397
 
        elif (PY_MAJOR_VERSION < 3) and isinstance(value, str):
398
 
            return value.decode('utf8')
399
 
        else:
400
 
            try:
401
 
                s = str(value)
402
 
                return self._s2b(s)
403
 
            except:
404
 
                raise TypeError('value not a string and not convertable')
405
 
        return
406
 
 
407
 
cdef class shitty_mcrypt(object):
408
 
    '''The wrapper class for mcrypt.'''
409
 
    cdef cmc.CRYPT_STREAM *_mcrypt_stream
410
 
 
411
 
    cdef char *_algo
412
 
    cdef char *_mode
413
 
 
414
 
    cdef bint _initialized
415
 
    cdef int _blockSize
416
 
    cdef bint _ivRequired
417
 
 
418
 
    cdef bytes iv
419
 
    cdef bytes key
420
 
    cdef bytes salt
421
 
 
422
 
    def __cinit__(self):
423
 
        '''Low-level object initialization.'''
424
 
        pass
425
 
 
426
 
    def _decode_parameter(self, param):
427
 
        if isinstance(param, bytes):
428
 
            return(param)
429
 
        if isinstance(param, unicode):
430
 
            return param.encode('utf8')
431
 
        elif (PY_MAJOR_VERSION < 3) and isinstance(param, str):
432
 
            return param.decode('utf8')
433
 
        else:
434
 
            raise TypeError('parameter must be a string')
435
 
 
436
 
    def __init__(self, algorithm, mode, **kwargs):
437
 
        '''Initializes an mcrypt instance.
438
 
 
439
 
        Note that this function must always be called: that means that
440
 
        if this class is subclassed for any reason, you MUST make sure
441
 
        that you call up to this constructor!
442
 
 
443
 
        As best as I can tell, the underlying API is not thread-safe;
444
 
        a single object must only be used by a single thread, or the
445
 
        program must exercise extreme care in accessing the object
446
 
        concurrently from multiple threads.
447
 
 
448
 
        After the object has been initialized, it can be used for
449
 
        encrypting any sort of input.
450
 
 
451
 
        Available **kwargs:
452
 
 
453
 
          algo_dir: The directory containing the module housing the
454
 
          custom algorithm.  If you don't know what this is, you need
455
 
          not use it.
456
 
 
457
 
          mode_dir: The directory containing the module housing the
458
 
          custom mode.  If you don't know what this is, you need not
459
 
          use it.'''
460
 
        self.iv = None
461
 
 
462
 
        _algo = self._decode_parameter(algorithm)
463
 
        _mode = self._decode_parameter(mode)
464
 
 
465
 
        self._openModule(_algo, _mode, **kwargs)
466
 
        if self._mcrypt_stream is NULL:
467
 
            raise Exception('mcrypt failed')
468
 
 
469
 
        self._algo = _algo
470
 
        self._mode = _mode
471
 
 
472
 
        self._blockSize = cmc.mcrypt_enc_get_block_size(self._mcrypt_stream)
473
 
        self._ivRequired = cmc.mcrypt_enc_mode_has_iv(self._mcrypt_stream)
474
 
 
475
 
        if self._ivRequired:
476
 
            self.iv = <char *>malloc(cmc.mcrypt_enc_get_iv_size(self._mcrypt_stream))
477
 
 
478
 
        self._initialized = True
479
 
        return
480
 
 
481
 
    # XXX: ass ugly
482
 
    def _openModule(self, _algo, _mode, **kwargs):
483
 
        _algo_dir = None
484
 
        _mode_dir = None
485
 
 
486
 
        if 'algo_dir' in kwargs:
487
 
            _algo_dir = self._decode_parameter(kwargs['algo_dir'])
488
 
 
489
 
        if 'algo_dir' in kwargs:
490
 
            _mode_dir = self._decode_parameter(kwargs['algo_dir'])
491
 
 
492
 
        if (_algo_dir is None) and (_mode_dir is None):
493
 
            self._mcrypt_stream = cmc.mcrypt_module_open(_algo, NULL,
494
 
                                                         _mode, NULL)
495
 
        elif (_algo_dir is None) and (_mode_dir is not None):
496
 
            self._mcrypt_stream = cmc.mcrypt_module_open(_algo, NULL,
497
 
                                                         _mode, _mode_dir)
498
 
        elif (_algo_dir is not None) and (_mode_dir is None):
499
 
            self._mcrypt_stream = cmc.mcrypt_module_open(_algo, _algo_dir,
500
 
                                                         _mode, NULL)
501
 
        else:
502
 
            self._mcrypt_stream = cmc.mcrypt_module_open(_algo, _algo_dir,
503
 
                                                         _mode, _mode_dir)
504
 
 
505
 
        return
506
 
 
507
 
    def get_iv_size(self):
508
 
        '''Retrieves the size of the IV required for this instance.
509
 
 
510
 
        If no IV is required, returns None to the caller; otherwise,
511
 
        the size of the IV is returned to the caller.
512
 
 
513
 
        Note that the IV size is in BYTES, not BITS.'''
514
 
 
515
 
        # Note: we do it this way because cmc.mcrypt_enc_mode_has_iv
516
 
        # may provide misleading results if the algorithm requires an
517
 
        # IV even when the current mode does not.
518
 
        iv_size = cmc.mcrypt_enc_get_iv_size(self._mcrypt_stream)
519
 
        if iv_size == 0:
520
 
            return None
521
 
        else:
522
 
            return iv_size
523
 
 
524
 
    def get_key_size(self):
525
 
        '''Retrieves the max supported key size.
526
 
 
527
 
        Note that the algorithm set for the instance may support key
528
 
        sizes other than the maximum; to find that out, use
529
 
        get_key_sizes(), which will return all permitted key sizes.
530
 
 
531
 
        Note that the key size is in BYTES, not BITS.'''
532
 
        return cmc.mcrypt_enc_get_key_size(self._mcrypt_stream)
533
 
 
534
 
    def set_password(self, password, salt = None):
535
 
        '''Sets the (encryption, decryption) password.
536
 
 
537
 
        The actual password is not saved: instead, the password is
538
 
        converted into a key, which is then used for the encryption
539
 
        and decryption.
540
 
 
541
 
        This function uses the OpenSSL implementation of the PBKDF2
542
 
        algorithm.'''
543
 
        salt = self._process_salt(salt)
544
 
        iterCount = 500000
545
 
 
546
 
        self.salt = salt
547
 
        self.key = self._set_key_pbkdf2(password, salt, iterCount,
548
 
                                        self.get_key_size())
549
 
        return (self.salt, self.key)
550
 
 
551
 
    def get_block_size(self):
552
 
        '''Retrieves the block size.
553
 
 
554
 
        Note that the block size is in BYTES, not BITS.'''
555
 
        return cmc.mcrypt_enc_get_block_size(self._mcrypt_stream)
556
 
 
557
 
    def generate_random_iv(self):
558
 
        '''Generates a pseudorandom IV value.
559
 
 
560
 
        Please note that this function makes NO CLAIM that the IV is
561
 
        selected with enough entropy to be universally useful.  If you
562
 
        have a preferred method of generating IVs which you feel is
563
 
        better than this method (which honestly is quite simplistic)
564
 
        then please feel free to let me know what it is and why it is
565
 
        better.  This code does not make any effort to generate
566
 
        high-quality random numbers.  Of course, one should rely on
567
 
        the secrecy of the key for security, and not necessarily the
568
 
        IV...'''
569
 
        iv_size = self.get_iv_size()
570
 
        if iv_size == 0:
571
 
            self.iv = None
572
 
        else:
573
 
            self.iv = os.urandom(iv_size)
574
 
        return
575
 
 
576
 
    def get_iv(self):
577
 
        '''Retrieves the IV, if set.'''
578
 
        return self.iv
579
 
 
580
 
    def _get_key(self, password, salt = None, length = 256):
581
 
        '''Fetches a very strong key.'''
582
 
        salt = self._process_salt(salt)
583
 
        iterCount = 500000
584
 
 
585
 
        return (salt, self._set_key_mtkdf0(password, salt,
586
 
                                           iterCount, length))
587
 
 
588
 
    def _process_salt(self, salt):
589
 
        if salt is None:
590
 
            salt = os.urandom(8)
591
 
        elif len(salt) < 8:
592
 
            raise ValueError('Salt must be > 8 bytes long')
593
 
        elif type(salt) != bytes:
594
 
            raise TypeError('Salt must be bytes, got {}'.format(type(salt)))
595
 
 
596
 
        return salt
597
 
 
598
 
    def _set_key_pbkdf1(self, password, salt, iterCount, keyLen = 0,
599
 
                        algo = 'md5'):
600
 
        supportedAlgos = { 'md5': { 'max_key_len': 16,
601
 
                                    'class': hashlib.md5 },
602
 
                           'sha1': { 'max_key_len': 20,
603
 
                                     'class': hashlib.sha1 } }
604
 
        if algo == 'md2':
605
 
            raise ValueError('md2 is unsupported (insecure since 2004)')
606
 
        elif algo not in supportedAlgos:
607
 
            raise ValueError('algo {} unsupported by PBKDF1'.format(algo))
608
 
 
609
 
        mkl = supportedAlgos[algo]['max_key_len']
610
 
        if keyLen == 0:
611
 
            keyLen = mkl
612
 
        elif keyLen > mkl:
613
 
            raise ValueError('max key len must not be > {}'.format(mkl))
614
 
 
615
 
        passwd = self._decode_parameter(password)
616
 
 
617
 
        hasherClass = supportedAlgos[algo]['class']
618
 
        hasher = hasherClass()
619
 
        hasher.update(passwd + salt)
620
 
        hashOutput = hasher.digest()
621
 
 
622
 
        for i in range(iterCount - 1):
623
 
            hasher = hasherClass()
624
 
            hasher.update(hashOutput)
625
 
            hashOutput = hasher.digest()
626
 
 
627
 
        return hashOutput[:keyLen]
628
 
 
629
 
    def _set_key_mtkdf0(self, password, salt, iterCount, keyLen = 0,
630
 
                        algo = 'sha1'):
631
 
        keyparts = []
632
 
        blockSize = 0
633
 
 
634
 
        if algo == 'md5':
635
 
            blockSize = 16
636
 
        elif algo == 'sha1':
637
 
            blockSize = 20
638
 
        else:
639
 
            raise ValueError('algo {} unsupported'.format(algo))
640
 
 
641
 
        requiredBlocks = math.ceil(keyLen / blockSize)
642
 
        iteration = 0
643
 
        for blk in range(requiredBlocks):
644
 
            sub_iters = math.ceil(iterCount / requiredBlocks) + iteration
645
 
            thisBlock = self._set_key_pbkdf1(password, salt,
646
 
                                             sub_iters, 0, algo)
647
 
            iteration += 1
648
 
            keyparts.append(thisBlock)
649
 
 
650
 
        bytes = b''
651
 
        for part in keyparts:
652
 
            bytes += part
653
 
 
654
 
        return bytes[:keyLen]
655
 
 
656
 
    def _set_key_pbkdf2(self, password, salt, iterCount, keyLen):
657
 
        if keyLen < 8:
658
 
            raise ValueError('No point to such a short key!')
659
 
 
660
 
        _realPass = self._decode_parameter(password)
661
 
        _realSalt = self._decode_parameter(salt)
662
 
 
663
 
        cdef unsigned char *_out = <unsigned char *>malloc(keyLen)
664
 
 
665
 
        success = cmc.PKCS5_PBKDF2_HMAC_SHA1(_realPass, len(_realPass),
666
 
                                             _realSalt, len(_realSalt),
667
 
                                             iterCount, keyLen,
668
 
                                             _out)
669
 
 
670
 
        bytes = _out[:keyLen]
671
 
        free(<void *>_out)
672
 
        return(bytes)
 
312
            kdf = pbkdf2
 
313
        #elif PY_MAJOR_VERSION == 2
 
314
        #    if callable(kdf) == False:
 
315
        #        raise ValueError('kdf must be callable')
 
316
        #elif PY_MAJOR_VERSION == 3:
 
317
        #    if hasattr(kdf, '__call__') == False:
 
318
        #        raise ValueError('kdf must be callable')
 
319
 
 
320
        if iters < 1000:
 
321
            msg = 'possibly insecure # of iterations'.format(iters)
 
322
            warnings.warn(msg, McryptSecurityWarning)
 
323
        self._kdf_iterations = iters
 
324
 
 
325
        if salt is not None:
 
326
            if len(_s2b(salt)) < 8:
 
327
                msg = 'extremely short salt in use'
 
328
                warnings.warn(msg, McryptSecurityWarning)
 
329
            self._salt = _s2b(salt)
 
330
        else:
 
331
            # is this secure/random enough?
 
332
            self._salt = os.urandom(8)
 
333
 
 
334
        if iv is not None:
 
335
            if len(_s2b(iv)) != self._iv_len:
 
336
                msg = 'iv must be {0} bytes exactly'
 
337
                raise ValueError(msg.format(self._iv_len))
 
338
            self._iv = _s2b(iv)
 
339
        else:
 
340
            # is this secure/random enough?
 
341
            self._iv = os.urandom(self._iv_len)
 
342
 
 
343
        if klen == 0:
 
344
            self._key_len = self._avail_key_sizes[-1]
 
345
        elif klen in self._avail_key_sizes:
 
346
            self._key_len = klen
 
347
        else:
 
348
            msg = 'klen must be one of {0}, not {1}'
 
349
            raise ValueError(msg.format(self._avail_key_sizes,
 
350
                                        klen))
 
351
 
 
352
        self._key = kdf(_s2b(passwd), self._salt, self._kdf_iterations,
 
353
                        self._key_len, **kwargs)
 
354
 
 
355
    def _close_mcrypt(self):
 
356
        if self._mcStream is not NULL:
 
357
            cmc.mcrypt_module_close(self._mcStream)
 
358
        self._mcStream = NULL
 
359
        return
 
360
 
 
361
    def _do_init(self):
 
362
        '''Handles variable init at object instantiation time.'''
 
363
        self._iv_len = cmc.mcrypt_enc_get_iv_size(self._mcStream)
 
364
        self._block_size = cmc.mcrypt_enc_get_block_size(self._mcStream)
 
365
        self._encdec_mode = 'none'
 
366
 
 
367
        self._avail_key_sizes = []
 
368
        cdef int *keyszs
 
369
        cdef int array_length
 
370
 
 
371
        keyszs = cmc.mcrypt_enc_get_supported_key_sizes(self._mcStream,
 
372
                                                        &array_length)
 
373
        for i in range(array_length):
 
374
            self._avail_key_sizes.append(keyszs[i])
 
375
 
 
376
        free(<void*>keyszs)
 
377
        return
 
378
 
 
379
    def _open_mcrypt(self, algo, mode):
 
380
        self._mcStream = cmc.mcrypt_module_open(algo, NULL,
 
381
                                                mode, NULL)
 
382
        if self._mcStream is NULL:
 
383
            msg = 'mcrypt init failed: a:{0} m:{1}'
 
384
            raise McryptError(msg.format(algo, mode))
 
385
        return
 
386
 
 
387
cdef class raw_encrypt(_mcrypt_base):
 
388
    '''raw_encrypt([algo[, mode]]) -> raw_encrypt object
 
389
    A class for encrypting data using the mcrypt library.
 
390
 
 
391
    This class provides encryption functionality to Python programs,
 
392
    built on the mcrypt library.  If unspecified, algo and mode will
 
393
    be set to default values, which for this release is AES
 
394
    (Rijndael-128) and CBC mode.  These defaults may change in the
 
395
    future, however.  The algorithm and the mode can be set to one of
 
396
    the constants defined in this module; see the module help for what
 
397
    those are.
 
398
 
 
399
    The encryption process provides a barebones encryption class; it
 
400
    does nothing but convert from plaintext to ciphertext,
 
401
    block-by-block.  Extra functionality comes from classes derived
 
402
    from raw_encrypt.'''
 
403
    cdef bint _running
 
404
    cdef int _blocks_processed
 
405
 
 
406
    def __init__(self, algo = ALGO_DEFAULT, mode = MODE_DEFAULT):
 
407
        super(raw_encrypt, self).__init__(algo, mode)
 
408
        self._encdec_mode = 'encrypt'
 
409
        return
 
410
 
 
411
    def begin(self):
 
412
        '''begin() -> bool
 
413
        Begins an encryption process.
 
414
 
 
415
        The encryption process is a state machine: it is started,
 
416
        stepped (presumably until the end of input) and then stopped
 
417
        (whereupon it can be restarted with a different input if
 
418
        desired).  It is an error to call this method when an
 
419
        encryption process is already running.'''
 
420
        if self._running == True:
 
421
            msg = 'attempt to start an already started encrypter'
 
422
            raise McryptError(msg)
 
423
 
 
424
        if len(self._iv) != self._iv_len:
 
425
            raise McryptError('IV is incorrectly set.')
 
426
        elif self._iv_len == 0:
 
427
            cmc.mcrypt_generic_init(self._mcStream,
 
428
                                    <void*> self._key,
 
429
                                    len(self._key),
 
430
                                    NULL)
 
431
        else:
 
432
            cmc.mcrypt_generic_init(self._mcStream,
 
433
                                    <void*> self._key,
 
434
                                    len(self._key),
 
435
                                    <void*> self._iv)
 
436
 
 
437
        self._blocks_processed = 0
 
438
        self._running = True
 
439
        return self._running
 
440
 
 
441
    def end(self):
 
442
        '''end() -> None
 
443
        Ends an encryption process.
 
444
 
 
445
        After an encryption process is ended, a new one can be begin.
 
446
        In effect, this is how object reuse is made possible.  It is
 
447
        an error to call this method when an encryption process is
 
448
        not running.'''
 
449
        if self._running == False:
 
450
            msg = 'attempt to end an already ended encrypter'
 
451
            raise McryptError(msg)
 
452
 
 
453
        cmc.mcrypt_generic_deinit(self._mcStream)
 
454
        return
 
455
 
 
456
    def get_blocks_processed(self):
 
457
        return self._blocks_processed
 
458
 
 
459
    def step(self, input):
 
460
        '''step(input) -> bytes
 
461
        Runs a single step of the encryption process.
 
462
 
 
463
        This function executes a single step of the encryption
 
464
        process; that is, it will encrypt whatever blocks of data are
 
465
        provided.  The input data length must be exactly a multiple of
 
466
        the current block size.  An exception will be raised if the
 
467
        data is incorrectly sized or if mcrypt returns an error.
 
468
 
 
469
        The return value is the encrypted block.'''
 
470
        if self._running == False:
 
471
            msg = 'attempt to step nonrunning encrypter'
 
472
            raise McryptError(msg)
 
473
        in_bin = _s2b(input)
 
474
        in_len = len(in_bin)
 
475
 
 
476
        if in_len % self._block_size > 0:
 
477
            msg = 'input size must be an interval of block size {0}'
 
478
            msg += '(e.g., size % {0} == 0 must be True)'
 
479
            raise ValueError(msg.format(self._block_size))
 
480
 
 
481
        cdef char* buffer = <char*>malloc(in_len)
 
482
        cmc.strncpy(buffer, in_bin, in_len)
 
483
        success = cmc.mcrypt_generic(self._mcStream, <void*>buffer, in_len)
 
484
 
 
485
        if success != 0:
 
486
            free(<void*>buffer)
 
487
            msg = 'mcrypt returned error {0}: {1}'
 
488
            raise McryptError(msg.format(success,
 
489
                                         cmc.mcrypt_strerror(success)))
 
490
 
 
491
        retval = buffer[:in_len]
 
492
        free(<void*>buffer)
 
493
 
 
494
        self._blocks_processed += 1
 
495
        return retval
 
496
 
 
497
cdef class raw_decrypt(_mcrypt_base):
 
498
    '''raw_decrypt([algo[, mode]]) -> raw_decrypt object
 
499
    A class for decrypting data using the mcrypt library.
 
500
 
 
501
    This class provides decryption functionality to Python programs,
 
502
    built on the mcrypt library.  If unspecified, algo and mode will
 
503
    be set to default values, which for this release is AES
 
504
    (Rijndael-128) and CBC mode.  These defaults may change in the
 
505
    future, however.  The algorithm and the mode can be set to one of
 
506
    the constants defined in this module; see the module help for what
 
507
    those are.
 
508
 
 
509
    The decryption process provides a barebones decryption class.  You
 
510
    must know and set all parameters for decryption, they are not
 
511
    automatically detected.  This class just takes ciphertext blocks
 
512
    and turns them into plaintext blocks.'''
 
513
    cdef bint _running
 
514
    cdef int _blocks_processed
 
515
 
 
516
    def __init__(self, algo = ALGO_DEFAULT, mode = MODE_DEFAULT):
 
517
        super(raw_decrypt, self).__init__(algo, mode)
 
518
        self._encdec_mode = 'decrypt'
 
519
        return
 
520
 
 
521
    def begin(self):
 
522
        '''begin() -> bool
 
523
        Begins a decryption process.
 
524
 
 
525
        The decryption process is a state machine: it is started,
 
526
        stepped (presumably until the end of input) and then stopped
 
527
        (whereupon it can be restarted with a different input if
 
528
        desired).  It is an error to call this method when a
 
529
        decryption process is already running.'''
 
530
        if self._running == True:
 
531
            msg = 'attempt to start an already started decrypter'
 
532
            raise McryptError(msg)
 
533
 
 
534
        if len(self._iv) != self._iv_len:
 
535
            raise McryptError('IV is incorrectly set')
 
536
        elif self._iv_len == 0:
 
537
            cmc.mcrypt_generic_init(self._mcStream,
 
538
                                    <void*> self._key,
 
539
                                    len(self._key),
 
540
                                    NULL)
 
541
        else:
 
542
            cmc.mcrypt_generic_init(self._mcStream,
 
543
                                    <void*> self._key,
 
544
                                    len(self._key),
 
545
                                    <void*> self._iv)
 
546
 
 
547
        self._blocks_processed = 0
 
548
        self._running = True
 
549
        return self._running
 
550
 
 
551
    def end(self):
 
552
        '''end() -> None
 
553
        Ends a decryption process.
 
554
 
 
555
        After a decryption process is ended, a new one can be begin.
 
556
        In effect, this is how object reuse is made possible.  It is
 
557
        an error to call this method when a decryption process is not
 
558
        running.'''
 
559
        if self._running == False:
 
560
            msg = 'attempt to end an already ended decrypter'
 
561
            raise McryptError(msg)
 
562
 
 
563
        cmc.mcrypt_generic_deinit(self._mcStream)
 
564
        return
 
565
 
 
566
    def step(self, input):
 
567
        '''step(input) -> bytes
 
568
        Runs a single step of the encryption process.
 
569
 
 
570
        This function executes a single step of the encryption
 
571
        process; that is, it will encrypt whatever blocks of data are
 
572
        provided.  The input data length must be exactly a multiple of
 
573
        the current block size.  An exception will be raised if the
 
574
        data is incorrectly sized or if mcrypt returns an error.
 
575
 
 
576
        The return value is the encrypted block.'''
 
577
        if self._running == False:
 
578
            msg = 'attempt to step nonrunning decrypter'
 
579
            raise McryptError(msg)
 
580
        in_bin = _s2b(input)
 
581
        in_len = len(in_bin)
 
582
 
 
583
        if in_len % self._block_size > 0:
 
584
            msg = 'input size must be an interval of block size {0}'
 
585
            msg += '(e.g., size % {0} == 0 must be True)'
 
586
            raise ValueError(msg.format(self._block_size))
 
587
 
 
588
        cdef char* buffer = <char*>malloc(in_len)
 
589
        cmc.strncpy(buffer, in_bin, in_len)
 
590
        success = cmc.mdecrypt_generic(self._mcStream, <void*>buffer, in_len)
 
591
 
 
592
        if success != 0:
 
593
            free(<void*>buffer)
 
594
            msg = 'mcrypt returned error {0}: {1}'
 
595
            raise McryptError(msg.format(success,
 
596
                                         cmc.mcrypt_strerror(success)))
 
597
 
 
598
        retval = buffer[:in_len]
 
599
        free(<void*>buffer)
 
600
 
 
601
        self._blocks_processed += 1
 
602
        return retval