Parcourir la source

Hue - Upgrade Python-RSA to safe version

- rsa-4.0 is the last supported in Python2.7
- Python3.8 has rsa-4.7 package

(cherry picked from commit 251f88b1e49e4f1a82b3788309a768a60f393158)
Prakash Ranade il y a 3 ans
Parent
commit
4837badcf7
49 fichiers modifiés avec 1491 ajouts et 1981 suppressions
  1. 0 25
      desktop/core/ext-py/rsa-3.4.2/PKG-INFO
  2. 0 441
      desktop/core/ext-py/rsa-3.4.2/rsa/_version133.py
  3. 0 513
      desktop/core/ext-py/rsa-3.4.2/rsa/_version200.py
  4. 0 135
      desktop/core/ext-py/rsa-3.4.2/rsa/bigfile.py
  5. 0 179
      desktop/core/ext-py/rsa-3.4.2/rsa/varblock.py
  6. 0 73
      desktop/core/ext-py/rsa-3.4.2/tests/test_bigfile.py
  7. 0 32
      desktop/core/ext-py/rsa-3.4.2/tests/test_compat.py
  8. 0 42
      desktop/core/ext-py/rsa-3.4.2/tests/test_key.py
  9. 0 44
      desktop/core/ext-py/rsa-3.4.2/tests/test_prime.py
  10. 0 88
      desktop/core/ext-py/rsa-3.4.2/tests/test_varblock.py
  11. 27 5
      desktop/core/ext-py/rsa-4.0/CHANGELOG.txt
  12. 0 0
      desktop/core/ext-py/rsa-4.0/LICENSE
  13. 0 0
      desktop/core/ext-py/rsa-4.0/MANIFEST.in
  14. 73 0
      desktop/core/ext-py/rsa-4.0/PKG-INFO
  15. 12 13
      desktop/core/ext-py/rsa-4.0/README.md
  16. 0 0
      desktop/core/ext-py/rsa-4.0/create_timing_table.py
  17. 7 7
      desktop/core/ext-py/rsa-4.0/rsa/__init__.py
  18. 41 27
      desktop/core/ext-py/rsa-4.0/rsa/_compat.py
  19. 0 0
      desktop/core/ext-py/rsa-4.0/rsa/asn1.py
  20. 5 100
      desktop/core/ext-py/rsa-4.0/rsa/cli.py
  21. 42 42
      desktop/core/ext-py/rsa-4.0/rsa/common.py
  22. 0 0
      desktop/core/ext-py/rsa-4.0/rsa/core.py
  23. 108 56
      desktop/core/ext-py/rsa-4.0/rsa/key.py
  24. 74 0
      desktop/core/ext-py/rsa-4.0/rsa/machine_size.py
  25. 2 1
      desktop/core/ext-py/rsa-4.0/rsa/parallel.py
  26. 13 12
      desktop/core/ext-py/rsa-4.0/rsa/pem.py
  27. 98 40
      desktop/core/ext-py/rsa-4.0/rsa/pkcs1.py
  28. 103 0
      desktop/core/ext-py/rsa-4.0/rsa/pkcs1_v2.py
  29. 36 13
      desktop/core/ext-py/rsa-4.0/rsa/prime.py
  30. 1 1
      desktop/core/ext-py/rsa-4.0/rsa/randnum.py
  31. 14 23
      desktop/core/ext-py/rsa-4.0/rsa/transform.py
  32. 0 0
      desktop/core/ext-py/rsa-4.0/rsa/util.py
  33. 10 11
      desktop/core/ext-py/rsa-4.0/setup.cfg
  34. 10 5
      desktop/core/ext-py/rsa-4.0/setup.py
  35. 0 0
      desktop/core/ext-py/rsa-4.0/tests/__init__.py
  36. 0 0
      desktop/core/ext-py/rsa-4.0/tests/private.pem
  37. 296 0
      desktop/core/ext-py/rsa-4.0/tests/test_cli.py
  38. 29 10
      desktop/core/ext-py/rsa-4.0/tests/test_common.py
  39. 80 0
      desktop/core/ext-py/rsa-4.0/tests/test_compat.py
  40. 0 0
      desktop/core/ext-py/rsa-4.0/tests/test_integers.py
  41. 79 0
      desktop/core/ext-py/rsa-4.0/tests/test_key.py
  42. 59 18
      desktop/core/ext-py/rsa-4.0/tests/test_load_save_keys.py
  43. 0 0
      desktop/core/ext-py/rsa-4.0/tests/test_parallel.py
  44. 31 3
      desktop/core/ext-py/rsa-4.0/tests/test_pem.py
  45. 36 9
      desktop/core/ext-py/rsa-4.0/tests/test_pkcs1.py
  46. 83 0
      desktop/core/ext-py/rsa-4.0/tests/test_pkcs1_v2.py
  47. 110 0
      desktop/core/ext-py/rsa-4.0/tests/test_prime.py
  48. 0 0
      desktop/core/ext-py/rsa-4.0/tests/test_strings.py
  49. 12 13
      desktop/core/ext-py/rsa-4.0/tests/test_transform.py

+ 0 - 25
desktop/core/ext-py/rsa-3.4.2/PKG-INFO

@@ -1,25 +0,0 @@
-Metadata-Version: 1.1
-Name: rsa
-Version: 3.4.2
-Summary: Pure-Python RSA implementation
-Home-page: https://stuvel.eu/rsa
-Author: Sybren A. Stuvel
-Author-email: sybren@stuvel.eu
-License: ASL 2
-Description: UNKNOWN
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: Education
-Classifier: Intended Audience :: Information Technology
-Classifier: License :: OSI Approved :: Apache Software License
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Topic :: Security :: Cryptography

+ 0 - 441
desktop/core/ext-py/rsa-3.4.2/rsa/_version133.py

@@ -1,441 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Deprecated version of the RSA module
-
-.. deprecated:: 2.0
-
-    This submodule is deprecated and will be completely removed as of version 4.0.
-
-Module for calculating large primes, and RSA encryption, decryption,
-signing and verification. Includes generating public and private keys.
-
-WARNING: this code implements the mathematics of RSA. It is not suitable for
-real-world secure cryptography purposes. It has not been reviewed by a security
-expert. It does not include padding of data. There are many ways in which the
-output of this module, when used without any modification, can be sucessfully
-attacked.
-"""
-
-__author__ = "Sybren Stuvel, Marloes de Boer and Ivo Tamboer"
-__date__ = "2010-02-05"
-__version__ = '1.3.3'
-
-# NOTE: Python's modulo can return negative numbers. We compensate for
-# this behaviour using the abs() function
-
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-from pickle import dumps, loads
-import base64
-import math
-import os
-import random
-import sys
-import types
-import zlib
-
-from rsa._compat import byte
-
-# Display a warning that this insecure version is imported.
-import warnings
-warnings.warn('Insecure version of the RSA module is imported as %s, be careful'
-        % __name__)
-warnings.warn('This submodule is deprecated and will be completely removed as of version 4.0.',
-              DeprecationWarning)
-
-
-def gcd(p, q):
-    """Returns the greatest common divisor of p and q
-
-
-    >>> gcd(42, 6)
-    6
-    """
-    if p<q: return gcd(q, p)
-    if q == 0: return p
-    return gcd(q, abs(p%q))
-
-def bytes2int(bytes):
-    """Converts a list of bytes or a string to an integer
-    """
-
-    if not (type(bytes) is types.ListType or type(bytes) is types.StringType):
-        raise TypeError("You must pass a string or a list")
-
-    # Convert byte stream to integer
-    integer = 0
-    for byte in bytes:
-        integer *= 256
-        if type(byte) is types.StringType: byte = ord(byte)
-        integer += byte
-
-    return integer
-
-def int2bytes(number):
-    """Converts a number to a string of bytes
-    """
-
-    if not (type(number) is types.LongType or type(number) is types.IntType):
-        raise TypeError("You must pass a long or an int")
-
-    string = ""
-
-    while number > 0:
-        string = "%s%s" % (byte(number & 0xFF), string)
-        number /= 256
-    
-    return string
-
-def fast_exponentiation(a, p, n):
-    """Calculates r = a^p mod n
-    """
-    result = a % n
-    remainders = []
-    while p != 1:
-        remainders.append(p & 1)
-        p = p >> 1
-    while remainders:
-        rem = remainders.pop()
-        result = ((a ** rem) * result ** 2) % n
-    return result
-
-def read_random_int(nbits):
-    """Reads a random integer of approximately nbits bits rounded up
-    to whole bytes"""
-
-    nbytes = ceil(nbits/8.)
-    randomdata = os.urandom(nbytes)
-    return bytes2int(randomdata)
-
-def ceil(x):
-    """ceil(x) -> int(math.ceil(x))"""
-
-    return int(math.ceil(x))
-    
-def randint(minvalue, maxvalue):
-    """Returns a random integer x with minvalue <= x <= maxvalue"""
-
-    # Safety - get a lot of random data even if the range is fairly
-    # small
-    min_nbits = 32
-
-    # The range of the random numbers we need to generate
-    range = maxvalue - minvalue
-
-    # Which is this number of bytes
-    rangebytes = ceil(math.log(range, 2) / 8.)
-
-    # Convert to bits, but make sure it's always at least min_nbits*2
-    rangebits = max(rangebytes * 8, min_nbits * 2)
-    
-    # Take a random number of bits between min_nbits and rangebits
-    nbits = random.randint(min_nbits, rangebits)
-    
-    return (read_random_int(nbits) % range) + minvalue
-
-def fermat_little_theorem(p):
-    """Returns 1 if p may be prime, and something else if p definitely
-    is not prime"""
-
-    a = randint(1, p-1)
-    return fast_exponentiation(a, p-1, p)
-
-def jacobi(a, b):
-    """Calculates the value of the Jacobi symbol (a/b)
-    """
-
-    if a % b == 0:
-        return 0
-    result = 1
-    while a > 1:
-        if a & 1:
-            if ((a-1)*(b-1) >> 2) & 1:
-                result = -result
-            b, a = a, b % a
-        else:
-            if ((b ** 2 - 1) >> 3) & 1:
-                result = -result
-            a = a >> 1
-    return result
-
-def jacobi_witness(x, n):
-    """Returns False if n is an Euler pseudo-prime with base x, and
-    True otherwise.
-    """
-
-    j = jacobi(x, n) % n
-    f = fast_exponentiation(x, (n-1)/2, n)
-
-    if j == f: return False
-    return True
-
-def randomized_primality_testing(n, k):
-    """Calculates whether n is composite (which is always correct) or
-    prime (which is incorrect with error probability 2**-k)
-
-    Returns False if the number if composite, and True if it's
-    probably prime.
-    """
-
-    q = 0.5     # Property of the jacobi_witness function
-
-    # t = int(math.ceil(k / math.log(1/q, 2)))
-    t = ceil(k / math.log(1/q, 2))
-    for i in range(t+1):
-        x = randint(1, n-1)
-        if jacobi_witness(x, n): return False
-    
-    return True
-
-def is_prime(number):
-    """Returns True if the number is prime, and False otherwise.
-    """
-
-    """
-    if not fermat_little_theorem(number) == 1:
-        # Not prime, according to Fermat's little theorem
-        return False
-    """
-
-    if randomized_primality_testing(number, 5):
-        # Prime, according to Jacobi
-        return True
-    
-    # Not prime
-    return False
-
-    
-def getprime(nbits):
-    """Returns a prime number of max. 'math.ceil(nbits/8)*8' bits. In
-    other words: nbits is rounded up to whole bytes.
-    """
-
-    nbytes = int(math.ceil(nbits/8.))
-
-    while True:
-        integer = read_random_int(nbits)
-
-        # Make sure it's odd
-        integer |= 1
-
-        # Test for primeness
-        if is_prime(integer): break
-
-        # Retry if not prime
-
-    return integer
-
-def are_relatively_prime(a, b):
-    """Returns True if a and b are relatively prime, and False if they
-    are not.
-    """
-
-    d = gcd(a, b)
-    return (d == 1)
-
-def find_p_q(nbits):
-    """Returns a tuple of two different primes of nbits bits"""
-
-    p = getprime(nbits)
-    while True:
-        q = getprime(nbits)
-        if not q == p: break
-    
-    return (p, q)
-
-def extended_euclid_gcd(a, b):
-    """Returns a tuple (d, i, j) such that d = gcd(a, b) = ia + jb
-    """
-
-    if b == 0:
-        return (a, 1, 0)
-
-    q = abs(a % b)
-    r = long(a / b)
-    (d, k, l) = extended_euclid_gcd(b, q)
-
-    return (d, l, k - l*r)
-
-# Main function: calculate encryption and decryption keys
-def calculate_keys(p, q, nbits):
-    """Calculates an encryption and a decryption key for p and q, and
-    returns them as a tuple (e, d)"""
-
-    n = p * q
-    phi_n = (p-1) * (q-1)
-
-    while True:
-        # Make sure e has enough bits so we ensure "wrapping" through
-        # modulo n
-        e = getprime(max(8, nbits/2))
-        if are_relatively_prime(e, n) and are_relatively_prime(e, phi_n): break
-
-    (d, i, j) = extended_euclid_gcd(e, phi_n)
-
-    if not d == 1:
-        raise Exception("e (%d) and phi_n (%d) are not relatively prime" % (e, phi_n))
-
-    if not (e * i) % phi_n == 1:
-        raise Exception("e (%d) and i (%d) are not mult. inv. modulo phi_n (%d)" % (e, i, phi_n))
-
-    return (e, i)
-
-
-def gen_keys(nbits):
-    """Generate RSA keys of nbits bits. Returns (p, q, e, d).
-
-    Note: this can take a long time, depending on the key size.
-    """
-
-    while True:
-        (p, q) = find_p_q(nbits)
-        (e, d) = calculate_keys(p, q, nbits)
-
-        # For some reason, d is sometimes negative. We don't know how
-        # to fix it (yet), so we keep trying until everything is shiny
-        if d > 0: break
-
-    return (p, q, e, d)
-
-def gen_pubpriv_keys(nbits):
-    """Generates public and private keys, and returns them as (pub,
-    priv).
-
-    The public key consists of a dict {e: ..., , n: ....). The private
-    key consists of a dict {d: ...., p: ...., q: ....).
-    """
-    
-    (p, q, e, d) = gen_keys(nbits)
-
-    return ( {'e': e, 'n': p*q}, {'d': d, 'p': p, 'q': q} )
-
-def encrypt_int(message, ekey, n):
-    """Encrypts a message using encryption key 'ekey', working modulo
-    n"""
-
-    if type(message) is types.IntType:
-        return encrypt_int(long(message), ekey, n)
-
-    if not type(message) is types.LongType:
-        raise TypeError("You must pass a long or an int")
-
-    if message > 0 and \
-            math.floor(math.log(message, 2)) > math.floor(math.log(n, 2)):
-        raise OverflowError("The message is too long")
-
-    return fast_exponentiation(message, ekey, n)
-
-def decrypt_int(cyphertext, dkey, n):
-    """Decrypts a cypher text using the decryption key 'dkey', working
-    modulo n"""
-
-    return encrypt_int(cyphertext, dkey, n)
-
-def sign_int(message, dkey, n):
-    """Signs 'message' using key 'dkey', working modulo n"""
-
-    return decrypt_int(message, dkey, n)
-
-def verify_int(signed, ekey, n):
-    """verifies 'signed' using key 'ekey', working modulo n"""
-
-    return encrypt_int(signed, ekey, n)
-
-def picklechops(chops):
-    """Pickles and base64encodes it's argument chops"""
-
-    value = zlib.compress(dumps(chops))
-    encoded = base64.encodestring(value)
-    return encoded.strip()
-
-def unpicklechops(string):
-    """base64decodes and unpickes it's argument string into chops"""
-
-    return loads(zlib.decompress(base64.decodestring(string)))
-
-def chopstring(message, key, n, funcref):
-    """Splits 'message' into chops that are at most as long as n,
-    converts these into integers, and calls funcref(integer, key, n)
-    for each chop.
-
-    Used by 'encrypt' and 'sign'.
-    """
-
-    msglen = len(message)
-    mbits = msglen * 8
-    nbits = int(math.floor(math.log(n, 2)))
-    nbytes = nbits / 8
-    blocks = msglen / nbytes
-
-    if msglen % nbytes > 0:
-        blocks += 1
-
-    cypher = []
-    
-    for bindex in range(blocks):
-        offset = bindex * nbytes
-        block = message[offset:offset+nbytes]
-        value = bytes2int(block)
-        cypher.append(funcref(value, key, n))
-
-    return picklechops(cypher)
-
-def gluechops(chops, key, n, funcref):
-    """Glues chops back together into a string.  calls
-    funcref(integer, key, n) for each chop.
-
-    Used by 'decrypt' and 'verify'.
-    """
-    message = ""
-
-    chops = unpicklechops(chops)
-    
-    for cpart in chops:
-        mpart = funcref(cpart, key, n)
-        message += int2bytes(mpart)
-    
-    return message
-
-def encrypt(message, key):
-    """Encrypts a string 'message' with the public key 'key'"""
-    
-    return chopstring(message, key['e'], key['n'], encrypt_int)
-
-def sign(message, key):
-    """Signs a string 'message' with the private key 'key'"""
-    
-    return chopstring(message, key['d'], key['p']*key['q'], decrypt_int)
-
-def decrypt(cypher, key):
-    """Decrypts a cypher with the private key 'key'"""
-
-    return gluechops(cypher, key['d'], key['p']*key['q'], decrypt_int)
-
-def verify(cypher, key):
-    """Verifies a cypher with the public key 'key'"""
-
-    return gluechops(cypher, key['e'], key['n'], encrypt_int)
-
-# Do doctest if we're not imported
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod()
-
-__all__ = ["gen_pubpriv_keys", "encrypt", "decrypt", "sign", "verify"]
-

+ 0 - 513
desktop/core/ext-py/rsa-3.4.2/rsa/_version200.py

@@ -1,513 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Deprecated version of the RSA module
-
-.. deprecated:: 3.0
-
-    This submodule is deprecated and will be completely removed as of version 4.0.
-
-"""
-
-__author__ = "Sybren Stuvel, Marloes de Boer, Ivo Tamboer, and Barry Mead"
-__date__ = "2010-02-08"
-__version__ = '2.0'
-
-import math
-import os
-import random
-import sys
-import types
-from rsa._compat import byte
-
-# Display a warning that this insecure version is imported.
-import warnings
-warnings.warn('Insecure version of the RSA module is imported as %s' % __name__)
-warnings.warn('This submodule is deprecated and will be completely removed as of version 4.0.',
-              DeprecationWarning)
-
-
-def bit_size(number):
-    """Returns the number of bits required to hold a specific long number"""
-
-    return int(math.ceil(math.log(number,2)))
-
-def gcd(p, q):
-    """Returns the greatest common divisor of p and q
-    >>> gcd(48, 180)
-    12
-    """
-    # Iterateive Version is faster and uses much less stack space
-    while q != 0:
-        if p < q: (p,q) = (q,p)
-        (p,q) = (q, p % q)
-    return p
-    
-
-def bytes2int(bytes):
-    r"""Converts a list of bytes or a string to an integer
-    """
-
-    if not (type(bytes) is types.ListType or type(bytes) is types.StringType):
-        raise TypeError("You must pass a string or a list")
-
-    # Convert byte stream to integer
-    integer = 0
-    for byte in bytes:
-        integer *= 256
-        if type(byte) is types.StringType: byte = ord(byte)
-        integer += byte
-
-    return integer
-
-def int2bytes(number):
-    """
-    Converts a number to a string of bytes
-    """
-
-    if not (type(number) is types.LongType or type(number) is types.IntType):
-        raise TypeError("You must pass a long or an int")
-
-    string = ""
-
-    while number > 0:
-        string = "%s%s" % (byte(number & 0xFF), string)
-        number /= 256
-    
-    return string
-
-def to64(number):
-    """Converts a number in the range of 0 to 63 into base 64 digit
-    character in the range of '0'-'9', 'A'-'Z', 'a'-'z','-','_'.
-    """
-
-    if not (type(number) is types.LongType or type(number) is types.IntType):
-        raise TypeError("You must pass a long or an int")
-
-    if 0 <= number <= 9:            #00-09 translates to '0' - '9'
-        return byte(number + 48)
-
-    if 10 <= number <= 35:
-        return byte(number + 55)     #10-35 translates to 'A' - 'Z'
-
-    if 36 <= number <= 61:
-        return byte(number + 61)     #36-61 translates to 'a' - 'z'
-
-    if number == 62:                # 62   translates to '-' (minus)
-        return byte(45)
-
-    if number == 63:                # 63   translates to '_' (underscore)
-        return byte(95)
-
-    raise ValueError('Invalid Base64 value: %i' % number)
-
-
-def from64(number):
-    """Converts an ordinal character value in the range of
-    0-9,A-Z,a-z,-,_ to a number in the range of 0-63.
-    """
-
-    if not (type(number) is types.LongType or type(number) is types.IntType):
-        raise TypeError("You must pass a long or an int")
-
-    if 48 <= number <= 57:         #ord('0') - ord('9') translates to 0-9
-        return(number - 48)
-
-    if 65 <= number <= 90:         #ord('A') - ord('Z') translates to 10-35
-        return(number - 55)
-
-    if 97 <= number <= 122:        #ord('a') - ord('z') translates to 36-61
-        return(number - 61)
-
-    if number == 45:               #ord('-') translates to 62
-        return(62)
-
-    if number == 95:               #ord('_') translates to 63
-        return(63)
-
-    raise ValueError('Invalid Base64 value: %i' % number)
-
-
-def int2str64(number):
-    """Converts a number to a string of base64 encoded characters in
-    the range of '0'-'9','A'-'Z,'a'-'z','-','_'.
-    """
-
-    if not (type(number) is types.LongType or type(number) is types.IntType):
-        raise TypeError("You must pass a long or an int")
-
-    string = ""
-
-    while number > 0:
-        string = "%s%s" % (to64(number & 0x3F), string)
-        number /= 64
-
-    return string
-
-
-def str642int(string):
-    """Converts a base64 encoded string into an integer.
-    The chars of this string in in the range '0'-'9','A'-'Z','a'-'z','-','_'
-    """
-
-    if not (type(string) is types.ListType or type(string) is types.StringType):
-        raise TypeError("You must pass a string or a list")
-
-    integer = 0
-    for byte in string:
-        integer *= 64
-        if type(byte) is types.StringType: byte = ord(byte)
-        integer += from64(byte)
-
-    return integer
-
-def read_random_int(nbits):
-    """Reads a random integer of approximately nbits bits rounded up
-    to whole bytes"""
-
-    nbytes = int(math.ceil(nbits/8.))
-    randomdata = os.urandom(nbytes)
-    return bytes2int(randomdata)
-
-def randint(minvalue, maxvalue):
-    """Returns a random integer x with minvalue <= x <= maxvalue"""
-
-    # Safety - get a lot of random data even if the range is fairly
-    # small
-    min_nbits = 32
-
-    # The range of the random numbers we need to generate
-    range = (maxvalue - minvalue) + 1
-
-    # Which is this number of bytes
-    rangebytes = ((bit_size(range) + 7) / 8)
-
-    # Convert to bits, but make sure it's always at least min_nbits*2
-    rangebits = max(rangebytes * 8, min_nbits * 2)
-    
-    # Take a random number of bits between min_nbits and rangebits
-    nbits = random.randint(min_nbits, rangebits)
-    
-    return (read_random_int(nbits) % range) + minvalue
-
-def jacobi(a, b):
-    """Calculates the value of the Jacobi symbol (a/b)
-    where both a and b are positive integers, and b is odd
-    """
-
-    if a == 0: return 0
-    result = 1
-    while a > 1:
-        if a & 1:
-            if ((a-1)*(b-1) >> 2) & 1:
-                result = -result
-            a, b = b % a, a
-        else:
-            if (((b * b) - 1) >> 3) & 1:
-                result = -result
-            a >>= 1
-    if a == 0: return 0
-    return result
-
-def jacobi_witness(x, n):
-    """Returns False if n is an Euler pseudo-prime with base x, and
-    True otherwise.
-    """
-
-    j = jacobi(x, n) % n
-    f = pow(x, (n-1)/2, n)
-
-    if j == f: return False
-    return True
-
-def randomized_primality_testing(n, k):
-    """Calculates whether n is composite (which is always correct) or
-    prime (which is incorrect with error probability 2**-k)
-
-    Returns False if the number is composite, and True if it's
-    probably prime.
-    """
-
-    # 50% of Jacobi-witnesses can report compositness of non-prime numbers
-
-    for i in range(k):
-        x = randint(1, n-1)
-        if jacobi_witness(x, n): return False
-    
-    return True
-
-def is_prime(number):
-    """Returns True if the number is prime, and False otherwise.
-    """
-
-    if randomized_primality_testing(number, 6):
-        # Prime, according to Jacobi
-        return True
-    
-    # Not prime
-    return False
-
-    
-def getprime(nbits):
-    """Returns a prime number of max. 'math.ceil(nbits/8)*8' bits. In
-    other words: nbits is rounded up to whole bytes.
-    """
-
-    while True:
-        integer = read_random_int(nbits)
-
-        # Make sure it's odd
-        integer |= 1
-
-        # Test for primeness
-        if is_prime(integer): break
-
-        # Retry if not prime
-
-    return integer
-
-def are_relatively_prime(a, b):
-    """Returns True if a and b are relatively prime, and False if they
-    are not.
-
-    >>> are_relatively_prime(2, 3)
-    1
-    >>> are_relatively_prime(2, 4)
-    0
-    """
-
-    d = gcd(a, b)
-    return (d == 1)
-
-def find_p_q(nbits):
-    """Returns a tuple of two different primes of nbits bits"""
-    pbits = nbits + (nbits/16)  #Make sure that p and q aren't too close
-    qbits = nbits - (nbits/16)  #or the factoring programs can factor n
-    p = getprime(pbits)
-    while True:
-        q = getprime(qbits)
-        #Make sure p and q are different.
-        if not q == p: break
-    return (p, q)
-
-def extended_gcd(a, b):
-    """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
-    """
-    # r = gcd(a,b) i = multiplicitive inverse of a mod b
-    #      or      j = multiplicitive inverse of b mod a
-    # Neg return values for i or j are made positive mod b or a respectively
-    # Iterateive Version is faster and uses much less stack space
-    x = 0
-    y = 1
-    lx = 1
-    ly = 0
-    oa = a                             #Remember original a/b to remove 
-    ob = b                             #negative values from return results
-    while b != 0:
-        q = long(a/b)
-        (a, b)  = (b, a % b)
-        (x, lx) = ((lx - (q * x)),x)
-        (y, ly) = ((ly - (q * y)),y)
-    if (lx < 0): lx += ob              #If neg wrap modulo orignal b
-    if (ly < 0): ly += oa              #If neg wrap modulo orignal a
-    return (a, lx, ly)                 #Return only positive values
-
-# Main function: calculate encryption and decryption keys
-def calculate_keys(p, q, nbits):
-    """Calculates an encryption and a decryption key for p and q, and
-    returns them as a tuple (e, d)"""
-
-    n = p * q
-    phi_n = (p-1) * (q-1)
-
-    while True:
-        # Make sure e has enough bits so we ensure "wrapping" through
-        # modulo n
-        e = max(65537,getprime(nbits/4))
-        if are_relatively_prime(e, n) and are_relatively_prime(e, phi_n): break
-
-    (d, i, j) = extended_gcd(e, phi_n)
-
-    if not d == 1:
-        raise Exception("e (%d) and phi_n (%d) are not relatively prime" % (e, phi_n))
-    if (i < 0):
-        raise Exception("New extended_gcd shouldn't return negative values")
-    if not (e * i) % phi_n == 1:
-        raise Exception("e (%d) and i (%d) are not mult. inv. modulo phi_n (%d)" % (e, i, phi_n))
-
-    return (e, i)
-
-
-def gen_keys(nbits):
-    """Generate RSA keys of nbits bits. Returns (p, q, e, d).
-
-    Note: this can take a long time, depending on the key size.
-    """
-
-    (p, q) = find_p_q(nbits)
-    (e, d) = calculate_keys(p, q, nbits)
-
-    return (p, q, e, d)
-
-def newkeys(nbits):
-    """Generates public and private keys, and returns them as (pub,
-    priv).
-
-    The public key consists of a dict {e: ..., , n: ....). The private
-    key consists of a dict {d: ...., p: ...., q: ....).
-    """
-    nbits = max(9,nbits)           # Don't let nbits go below 9 bits
-    (p, q, e, d) = gen_keys(nbits)
-
-    return ( {'e': e, 'n': p*q}, {'d': d, 'p': p, 'q': q} )
-
-def encrypt_int(message, ekey, n):
-    """Encrypts a message using encryption key 'ekey', working modulo n"""
-
-    if type(message) is types.IntType:
-        message = long(message)
-
-    if not type(message) is types.LongType:
-        raise TypeError("You must pass a long or int")
-
-    if message < 0 or message > n:
-        raise OverflowError("The message is too long")
-
-    #Note: Bit exponents start at zero (bit counts start at 1) this is correct
-    safebit = bit_size(n) - 2                   #compute safe bit (MSB - 1)
-    message += (1 << safebit)                   #add safebit to ensure folding
-
-    return pow(message, ekey, n)
-
-def decrypt_int(cyphertext, dkey, n):
-    """Decrypts a cypher text using the decryption key 'dkey', working
-    modulo n"""
-
-    message = pow(cyphertext, dkey, n)
-
-    safebit = bit_size(n) - 2                   #compute safe bit (MSB - 1)
-    message -= (1 << safebit)                   #remove safebit before decode
-
-    return message
-
-def encode64chops(chops):
-    """base64encodes chops and combines them into a ',' delimited string"""
-
-    chips = []                              #chips are character chops
-
-    for value in chops:
-        chips.append(int2str64(value))
-
-    #delimit chops with comma
-    encoded = ','.join(chips)
-
-    return encoded
-
-def decode64chops(string):
-    """base64decodes and makes a ',' delimited string into chops"""
-
-    chips = string.split(',')               #split chops at commas
-
-    chops = []
-
-    for string in chips:                    #make char chops (chips) into chops
-        chops.append(str642int(string))
-
-    return chops
-
-def chopstring(message, key, n, funcref):
-    """Chops the 'message' into integers that fit into n,
-    leaving room for a safebit to be added to ensure that all
-    messages fold during exponentiation.  The MSB of the number n
-    is not independant modulo n (setting it could cause overflow), so
-    use the next lower bit for the safebit.  Therefore reserve 2-bits
-    in the number n for non-data bits.  Calls specified encryption
-    function for each chop.
-
-    Used by 'encrypt' and 'sign'.
-    """
-
-    msglen = len(message)
-    mbits = msglen * 8
-    #Set aside 2-bits so setting of safebit won't overflow modulo n.
-    nbits = bit_size(n) - 2             # leave room for safebit
-    nbytes = nbits / 8
-    blocks = msglen / nbytes
-
-    if msglen % nbytes > 0:
-        blocks += 1
-
-    cypher = []
-    
-    for bindex in range(blocks):
-        offset = bindex * nbytes
-        block = message[offset:offset+nbytes]
-        value = bytes2int(block)
-        cypher.append(funcref(value, key, n))
-
-    return encode64chops(cypher)   #Encode encrypted ints to base64 strings
-
-def gluechops(string, key, n, funcref):
-    """Glues chops back together into a string.  calls
-    funcref(integer, key, n) for each chop.
-
-    Used by 'decrypt' and 'verify'.
-    """
-    message = ""
-
-    chops = decode64chops(string)  #Decode base64 strings into integer chops
-    
-    for cpart in chops:
-        mpart = funcref(cpart, key, n) #Decrypt each chop
-        message += int2bytes(mpart)    #Combine decrypted strings into a msg
-    
-    return message
-
-def encrypt(message, key):
-    """Encrypts a string 'message' with the public key 'key'"""
-    if 'n' not in key:
-        raise Exception("You must use the public key with encrypt")
-
-    return chopstring(message, key['e'], key['n'], encrypt_int)
-
-def sign(message, key):
-    """Signs a string 'message' with the private key 'key'"""
-    if 'p' not in key:
-        raise Exception("You must use the private key with sign")
-
-    return chopstring(message, key['d'], key['p']*key['q'], encrypt_int)
-
-def decrypt(cypher, key):
-    """Decrypts a string 'cypher' with the private key 'key'"""
-    if 'p' not in key:
-        raise Exception("You must use the private key with decrypt")
-
-    return gluechops(cypher, key['d'], key['p']*key['q'], decrypt_int)
-
-def verify(cypher, key):
-    """Verifies a string 'cypher' with the public key 'key'"""
-    if 'n' not in key:
-        raise Exception("You must use the public key with verify")
-
-    return gluechops(cypher, key['e'], key['n'], decrypt_int)
-
-# Do doctest if we're not imported
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod()
-
-__all__ = ["newkeys", "encrypt", "decrypt", "sign", "verify"]
-

+ 0 - 135
desktop/core/ext-py/rsa-3.4.2/rsa/bigfile.py

@@ -1,135 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Large file support
-
-.. deprecated:: 3.4
-
-    The VARBLOCK format is NOT recommended for general use, has been deprecated since
-    Python-RSA 3.4, and will be removed in a future release. It's vulnerable to a
-    number of attacks:
-
-    1. decrypt/encrypt_bigfile() does not implement `Authenticated encryption`_ nor
-       uses MACs to verify messages before decrypting public key encrypted messages.
-
-    2. decrypt/encrypt_bigfile() does not use hybrid encryption (it uses plain RSA)
-       and has no method for chaining, so block reordering is possible.
-
-    See `issue #19 on Github`_ for more information.
-
-.. _Authenticated encryption: https://en.wikipedia.org/wiki/Authenticated_encryption
-.. _issue #19 on Github: https://github.com/sybrenstuvel/python-rsa/issues/13
-
-
-This module contains functions to:
-
-    - break a file into smaller blocks, and encrypt them, and store the
-      encrypted blocks in another file.
-
-    - take such an encrypted files, decrypt its blocks, and reconstruct the
-      original file.
-
-The encrypted file format is as follows, where || denotes byte concatenation:
-
-    FILE := VERSION || BLOCK || BLOCK ...
-
-    BLOCK := LENGTH || DATA
-
-    LENGTH := varint-encoded length of the subsequent data. Varint comes from
-    Google Protobuf, and encodes an integer into a variable number of bytes.
-    Each byte uses the 7 lowest bits to encode the value. The highest bit set
-    to 1 indicates the next byte is also part of the varint. The last byte will
-    have this bit set to 0.
-
-This file format is called the VARBLOCK format, in line with the varint format
-used to denote the block sizes.
-
-"""
-
-import warnings
-
-from rsa import key, common, pkcs1, varblock
-from rsa._compat import byte
-
-
-def encrypt_bigfile(infile, outfile, pub_key):
-    """Encrypts a file, writing it to 'outfile' in VARBLOCK format.
-
-    .. deprecated:: 3.4
-        This function was deprecated in Python-RSA version 3.4 due to security issues
-        in the VARBLOCK format. See the documentation_ for more information.
-
-    .. _documentation: https://stuvel.eu/python-rsa-doc/usage.html#working-with-big-files
-
-    :param infile: file-like object to read the cleartext from
-    :param outfile: file-like object to write the crypto in VARBLOCK format to
-    :param pub_key: :py:class:`rsa.PublicKey` to encrypt with
-
-    """
-
-    warnings.warn("The 'rsa.bigfile.encrypt_bigfile' function was deprecated in Python-RSA version "
-                  "3.4 due to security issues in the VARBLOCK format. See "
-                  "https://stuvel.eu/python-rsa-doc/usage.html#working-with-big-files "
-                  "for more information.",
-                  DeprecationWarning, stacklevel=2)
-
-    if not isinstance(pub_key, key.PublicKey):
-        raise TypeError('Public key required, but got %r' % pub_key)
-
-    key_bytes = common.bit_size(pub_key.n) // 8
-    blocksize = key_bytes - 11  # keep space for PKCS#1 padding
-
-    # Write the version number to the VARBLOCK file
-    outfile.write(byte(varblock.VARBLOCK_VERSION))
-
-    # Encrypt and write each block
-    for block in varblock.yield_fixedblocks(infile, blocksize):
-        crypto = pkcs1.encrypt(block, pub_key)
-
-        varblock.write_varint(outfile, len(crypto))
-        outfile.write(crypto)
-
-
-def decrypt_bigfile(infile, outfile, priv_key):
-    """Decrypts an encrypted VARBLOCK file, writing it to 'outfile'
-
-    .. deprecated:: 3.4
-        This function was deprecated in Python-RSA version 3.4 due to security issues
-        in the VARBLOCK format. See the documentation_ for more information.
-
-    .. _documentation: https://stuvel.eu/python-rsa-doc/usage.html#working-with-big-files
-
-    :param infile: file-like object to read the crypto in VARBLOCK format from
-    :param outfile: file-like object to write the cleartext to
-    :param priv_key: :py:class:`rsa.PrivateKey` to decrypt with
-
-    """
-
-    warnings.warn("The 'rsa.bigfile.decrypt_bigfile' function was deprecated in Python-RSA version "
-                  "3.4 due to security issues in the VARBLOCK format. See "
-                  "https://stuvel.eu/python-rsa-doc/usage.html#working-with-big-files "
-                  "for more information.",
-                  DeprecationWarning, stacklevel=2)
-
-    if not isinstance(priv_key, key.PrivateKey):
-        raise TypeError('Private key required, but got %r' % priv_key)
-
-    for block in varblock.yield_varblocks(infile):
-        cleartext = pkcs1.decrypt(block, priv_key)
-        outfile.write(cleartext)
-
-
-__all__ = ['encrypt_bigfile', 'decrypt_bigfile']

+ 0 - 179
desktop/core/ext-py/rsa-3.4.2/rsa/varblock.py

@@ -1,179 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""VARBLOCK file support
-
-.. deprecated:: 3.4
-
-    The VARBLOCK format is NOT recommended for general use, has been deprecated since
-    Python-RSA 3.4, and will be removed in a future release. It's vulnerable to a
-    number of attacks:
-
-    1. decrypt/encrypt_bigfile() does not implement `Authenticated encryption`_ nor
-       uses MACs to verify messages before decrypting public key encrypted messages.
-
-    2. decrypt/encrypt_bigfile() does not use hybrid encryption (it uses plain RSA)
-       and has no method for chaining, so block reordering is possible.
-
-    See `issue #19 on Github`_ for more information.
-
-.. _Authenticated encryption: https://en.wikipedia.org/wiki/Authenticated_encryption
-.. _issue #19 on Github: https://github.com/sybrenstuvel/python-rsa/issues/13
-
-
-The VARBLOCK file format is as follows, where || denotes byte concatenation:
-
-    FILE := VERSION || BLOCK || BLOCK ...
-
-    BLOCK := LENGTH || DATA
-
-    LENGTH := varint-encoded length of the subsequent data. Varint comes from
-    Google Protobuf, and encodes an integer into a variable number of bytes.
-    Each byte uses the 7 lowest bits to encode the value. The highest bit set
-    to 1 indicates the next byte is also part of the varint. The last byte will
-    have this bit set to 0.
-
-This file format is called the VARBLOCK format, in line with the varint format
-used to denote the block sizes.
-
-"""
-
-import warnings
-
-from rsa._compat import byte, b
-
-ZERO_BYTE = b('\x00')
-VARBLOCK_VERSION = 1
-
-warnings.warn("The 'rsa.varblock' module was deprecated in Python-RSA version "
-              "3.4 due to security issues in the VARBLOCK format. See "
-              "https://github.com/sybrenstuvel/python-rsa/issues/13 for more information.",
-              DeprecationWarning)
-
-
-def read_varint(infile):
-    """Reads a varint from the file.
-
-    When the first byte to be read indicates EOF, (0, 0) is returned. When an
-    EOF occurs when at least one byte has been read, an EOFError exception is
-    raised.
-
-    :param infile: the file-like object to read from. It should have a read()
-        method.
-    :returns: (varint, length), the read varint and the number of read bytes.
-    """
-
-    varint = 0
-    read_bytes = 0
-
-    while True:
-        char = infile.read(1)
-        if len(char) == 0:
-            if read_bytes == 0:
-                return 0, 0
-            raise EOFError('EOF while reading varint, value is %i so far' %
-                           varint)
-
-        byte = ord(char)
-        varint += (byte & 0x7F) << (7 * read_bytes)
-
-        read_bytes += 1
-
-        if not byte & 0x80:
-            return varint, read_bytes
-
-
-def write_varint(outfile, value):
-    """Writes a varint to a file.
-
-    :param outfile: the file-like object to write to. It should have a write()
-        method.
-    :returns: the number of written bytes.
-    """
-
-    # there is a big difference between 'write the value 0' (this case) and
-    # 'there is nothing left to write' (the false-case of the while loop)
-
-    if value == 0:
-        outfile.write(ZERO_BYTE)
-        return 1
-
-    written_bytes = 0
-    while value > 0:
-        to_write = value & 0x7f
-        value >>= 7
-
-        if value > 0:
-            to_write |= 0x80
-
-        outfile.write(byte(to_write))
-        written_bytes += 1
-
-    return written_bytes
-
-
-def yield_varblocks(infile):
-    """Generator, yields each block in the input file.
-
-    :param infile: file to read, is expected to have the VARBLOCK format as
-        described in the module's docstring.
-    @yields the contents of each block.
-    """
-
-    # Check the version number
-    first_char = infile.read(1)
-    if len(first_char) == 0:
-        raise EOFError('Unable to read VARBLOCK version number')
-
-    version = ord(first_char)
-    if version != VARBLOCK_VERSION:
-        raise ValueError('VARBLOCK version %i not supported' % version)
-
-    while True:
-        (block_size, read_bytes) = read_varint(infile)
-
-        # EOF at block boundary, that's fine.
-        if read_bytes == 0 and block_size == 0:
-            break
-
-        block = infile.read(block_size)
-
-        read_size = len(block)
-        if read_size != block_size:
-            raise EOFError('Block size is %i, but could read only %i bytes' %
-                           (block_size, read_size))
-
-        yield block
-
-
-def yield_fixedblocks(infile, blocksize):
-    """Generator, yields each block of ``blocksize`` bytes in the input file.
-
-    :param infile: file to read and separate in blocks.
-    :returns: a generator that yields the contents of each block
-    """
-
-    while True:
-        block = infile.read(blocksize)
-
-        read_bytes = len(block)
-        if read_bytes == 0:
-            break
-
-        yield block
-
-        if read_bytes < blocksize:
-            break

+ 0 - 73
desktop/core/ext-py/rsa-3.4.2/tests/test_bigfile.py

@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Tests block operations."""
-
-from rsa._compat import b
-
-try:
-    from StringIO import StringIO as BytesIO
-except ImportError:
-    from io import BytesIO
-import unittest
-
-import rsa
-from rsa import bigfile, varblock, pkcs1
-
-
-class BigfileTest(unittest.TestCase):
-    def test_encrypt_decrypt_bigfile(self):
-        # Expected block size + 11 bytes padding
-        pub_key, priv_key = rsa.newkeys((6 + 11) * 8)
-
-        # Encrypt the file
-        message = b('123456Sybren')
-        infile = BytesIO(message)
-        outfile = BytesIO()
-
-        bigfile.encrypt_bigfile(infile, outfile, pub_key)
-
-        # Test
-        crypto = outfile.getvalue()
-
-        cryptfile = BytesIO(crypto)
-        clearfile = BytesIO()
-
-        bigfile.decrypt_bigfile(cryptfile, clearfile, priv_key)
-        self.assertEquals(clearfile.getvalue(), message)
-
-        # We have 2x6 bytes in the message, so that should result in two
-        # bigfile.
-        cryptfile.seek(0)
-        varblocks = list(varblock.yield_varblocks(cryptfile))
-        self.assertEqual(2, len(varblocks))
-
-    def test_sign_verify_bigfile(self):
-        # Large enough to store MD5-sum and ASN.1 code for MD5
-        pub_key, priv_key = rsa.newkeys((34 + 11) * 8)
-
-        # Sign the file
-        msgfile = BytesIO(b('123456Sybren'))
-        signature = pkcs1.sign(msgfile, priv_key, 'MD5')
-
-        # Check the signature
-        msgfile.seek(0)
-        self.assertTrue(pkcs1.verify(msgfile, signature, pub_key))
-
-        # Alter the message, re-check
-        msgfile = BytesIO(b('123456sybren'))
-        self.assertRaises(pkcs1.VerificationError,
-                          pkcs1.verify, msgfile, signature, pub_key)

+ 0 - 32
desktop/core/ext-py/rsa-3.4.2/tests/test_compat.py

@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-import unittest
-import struct
-
-from rsa._compat import is_bytes, byte
-
-
-class TestByte(unittest.TestCase):
-    def test_byte(self):
-        for i in range(256):
-            byt = byte(i)
-            self.assertTrue(is_bytes(byt))
-            self.assertEqual(ord(byt), i)
-
-    def test_raises_StructError_on_overflow(self):
-        self.assertRaises(struct.error, byte, 256)
-        self.assertRaises(struct.error, byte, -1)

+ 0 - 42
desktop/core/ext-py/rsa-3.4.2/tests/test_key.py

@@ -1,42 +0,0 @@
-"""
-Some tests for the rsa/key.py file.
-"""
-
-import unittest
-
-import rsa.key
-import rsa.core
-
-
-class BlindingTest(unittest.TestCase):
-    def test_blinding(self):
-        """Test blinding and unblinding.
-
-        This is basically the doctest of the PrivateKey.blind method, but then
-        implemented as unittest to allow running on different Python versions.
-        """
-
-        pk = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
-
-        message = 12345
-        encrypted = rsa.core.encrypt_int(message, pk.e, pk.n)
-
-        blinded = pk.blind(encrypted, 4134431)  # blind before decrypting
-        decrypted = rsa.core.decrypt_int(blinded, pk.d, pk.n)
-        unblinded = pk.unblind(decrypted, 4134431)
-
-        self.assertEqual(unblinded, message)
-
-
-class KeyGenTest(unittest.TestCase):
-    def test_custom_exponent(self):
-        priv, pub = rsa.key.newkeys(16, exponent=3)
-
-        self.assertEqual(3, priv.e)
-        self.assertEqual(3, pub.e)
-
-    def test_default_exponent(self):
-        priv, pub = rsa.key.newkeys(16)
-
-        self.assertEqual(0x10001, priv.e)
-        self.assertEqual(0x10001, pub.e)

+ 0 - 44
desktop/core/ext-py/rsa-3.4.2/tests/test_prime.py

@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Tests prime functions."""
-
-import unittest
-
-import rsa.prime
-
-
-class PrimeTest(unittest.TestCase):
-    def test_is_prime(self):
-        """Test some common primes."""
-
-        # Test some trivial numbers
-        self.assertFalse(rsa.prime.is_prime(-1))
-        self.assertFalse(rsa.prime.is_prime(0))
-        self.assertFalse(rsa.prime.is_prime(1))
-        self.assertTrue(rsa.prime.is_prime(2))
-        self.assertFalse(rsa.prime.is_prime(42))
-        self.assertTrue(rsa.prime.is_prime(41))
-
-        # Test some slightly larger numbers
-        self.assertEqual(
-            [907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997],
-            [x for x in range(901, 1000) if rsa.prime.is_prime(x)]
-        )
-
-        # Test around the 50th millionth known prime.
-        self.assertTrue(rsa.prime.is_prime(982451653))
-        self.assertFalse(rsa.prime.is_prime(982451653 * 961748941))

+ 0 - 88
desktop/core/ext-py/rsa-3.4.2/tests/test_varblock.py

@@ -1,88 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-
-"""Tests varblock operations."""
-
-try:
-    from StringIO import StringIO as BytesIO
-except ImportError:
-    from io import BytesIO
-import unittest
-
-from rsa._compat import b
-from rsa import varblock
-
-
-class VarintTest(unittest.TestCase):
-    def test_read_varint(self):
-        encoded = b('\xac\x02crummy')
-        infile = BytesIO(encoded)
-
-        (decoded, read) = varblock.read_varint(infile)
-
-        # Test the returned values
-        self.assertEqual(300, decoded)
-        self.assertEqual(2, read)
-
-        # The rest of the file should be untouched
-        self.assertEqual(b('crummy'), infile.read())
-
-    def test_read_zero(self):
-        encoded = b('\x00crummy')
-        infile = BytesIO(encoded)
-
-        (decoded, read) = varblock.read_varint(infile)
-
-        # Test the returned values
-        self.assertEqual(0, decoded)
-        self.assertEqual(1, read)
-
-        # The rest of the file should be untouched
-        self.assertEqual(b('crummy'), infile.read())
-
-    def test_write_varint(self):
-        expected = b('\xac\x02')
-        outfile = BytesIO()
-
-        written = varblock.write_varint(outfile, 300)
-
-        # Test the returned values
-        self.assertEqual(expected, outfile.getvalue())
-        self.assertEqual(2, written)
-
-    def test_write_zero(self):
-        outfile = BytesIO()
-        written = varblock.write_varint(outfile, 0)
-
-        # Test the returned values
-        self.assertEqual(b('\x00'), outfile.getvalue())
-        self.assertEqual(1, written)
-
-
-class VarblockTest(unittest.TestCase):
-    def test_yield_varblock(self):
-        infile = BytesIO(b('\x01\x0512345\x06Sybren'))
-
-        varblocks = list(varblock.yield_varblocks(infile))
-        self.assertEqual([b('12345'), b('Sybren')], varblocks)
-
-
-class FixedblockTest(unittest.TestCase):
-    def test_yield_fixedblock(self):
-        infile = BytesIO(b('123456Sybren'))
-
-        fixedblocks = list(varblock.yield_fixedblocks(infile, 6))
-        self.assertEqual([b('123456'), b('Sybren')], fixedblocks)

+ 27 - 5
desktop/core/ext-py/rsa-3.4.2/CHANGELOG.txt → desktop/core/ext-py/rsa-4.0/CHANGELOG.txt

@@ -1,7 +1,30 @@
 Python-RSA changelog
 Python-RSA changelog
 ========================================
 ========================================
 
 
-Version 3.4.2 - released 2016-03-26
+Version 4.0 - released 2018-09-16
+----------------------------------------
+
+- Removed deprecated modules:
+    - rsa.varblock
+    - rsa.bigfile
+    - rsa._version133
+    - rsa._version200
+- Removed CLI commands that use the VARBLOCK/bigfile format.
+- Ensured that PublicKey.save_pkcs1() and PrivateKey.save_pkcs1() always return bytes.
+- Dropped support for Python 2.6 and 3.3.
+- Dropped support for Psyco.
+- Miller-Rabin iterations determined by bitsize of key.
+  [#58](https://github.com/sybrenstuvel/python-rsa/pull/58)
+- Added function `rsa.find_signature_hash()` to return the name of the hashing
+  algorithm used to sign a message. `rsa.verify()` now also returns that name,
+  instead of always returning `True`.
+  [#78](https://github.com/sybrenstuvel/python-rsa/issues/13)
+- Add support for SHA-224 for PKCS1 signatures.
+  [#104](https://github.com/sybrenstuvel/python-rsa/pull/104)
+- Transitioned from `requirements.txt` to Pipenv for package management.
+
+
+Version 3.4.2 - released 2016-03-29
 ----------------------------------------
 ----------------------------------------
 
 
 - Fixed dates in CHANGELOG.txt
 - Fixed dates in CHANGELOG.txt
@@ -17,7 +40,7 @@ Version 3.4.1 - released 2016-03-26
 Version 3.4 - released 2016-03-17
 Version 3.4 - released 2016-03-17
 ----------------------------------------
 ----------------------------------------
 
 
-- Moved development to Github: https://github.com/sybrenstuvel/python-rsa
+- Moved development to GitHub: https://github.com/sybrenstuvel/python-rsa
 - Solved side-channel vulnerability by implementing blinding, fixes #19
 - Solved side-channel vulnerability by implementing blinding, fixes #19
 - Deprecated the VARBLOCK format and rsa.bigfile module due to security issues, see
 - Deprecated the VARBLOCK format and rsa.bigfile module due to security issues, see
     https://github.com/sybrenstuvel/python-rsa/issues/13
     https://github.com/sybrenstuvel/python-rsa/issues/13
@@ -33,7 +56,7 @@ Version 3.4 - released 2016-03-17
 [1] https://travis-ci.org/sybrenstuvel/python-rsa
 [1] https://travis-ci.org/sybrenstuvel/python-rsa
 [2] https://coveralls.io/github/sybrenstuvel/python-rsa
 [2] https://coveralls.io/github/sybrenstuvel/python-rsa
 [3] https://codeclimate.com/github/sybrenstuvel/python-rsa
 [3] https://codeclimate.com/github/sybrenstuvel/python-rsa
-[4] http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pd
+[4] http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
 
 
 
 
 Version 3.3 - released 2016-01-13
 Version 3.3 - released 2016-01-13
@@ -121,7 +144,7 @@ Version 3.0 - released 2011-08-05
   the size of both ``p`` and ``q``. This is the common interpretation of
   the size of both ``p`` and ``q``. This is the common interpretation of
   RSA keysize. To get the old behaviour, double the keysize when generating a
   RSA keysize. To get the old behaviour, double the keysize when generating a
   new key.
   new key.
-  
+
 - Added a lot of doctests
 - Added a lot of doctests
 
 
 - Added random-padded encryption and decryption using PKCS#1 version 1.5
 - Added random-padded encryption and decryption using PKCS#1 version 1.5
@@ -139,4 +162,3 @@ Version 2.0
 ----------------------------------------
 ----------------------------------------
 
 
 - Security improvements by Barry Mead.
 - Security improvements by Barry Mead.
-

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/LICENSE → desktop/core/ext-py/rsa-4.0/LICENSE


+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/MANIFEST.in → desktop/core/ext-py/rsa-4.0/MANIFEST.in


+ 73 - 0
desktop/core/ext-py/rsa-4.0/PKG-INFO

@@ -0,0 +1,73 @@
+Metadata-Version: 2.1
+Name: rsa
+Version: 4.0
+Summary: Pure-Python RSA implementation
+Home-page: https://stuvel.eu/rsa
+Author: Sybren A. Stuvel
+Author-email: sybren@stuvel.eu
+Maintainer: Sybren A. Stuvel
+Maintainer-email: sybren@stuvel.eu
+License: ASL 2
+Description: Pure Python RSA implementation
+        ==============================
+        
+        [![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/)
+        [![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa)
+        [![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master)
+        [![Code Climate](https://img.shields.io/codeclimate/github/sybrenstuvel/python-rsa.svg)](https://codeclimate.com/github/sybrenstuvel/python-rsa)
+        
+        [Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports
+        encryption and decryption, signing and verifying signatures, and key
+        generation according to PKCS#1 version 1.5. It can be used as a Python
+        library as well as on the commandline. The code was mostly written by
+        Sybren A.  Stüvel.
+        
+        Documentation can be found at the [Python-RSA homepage](https://stuvel.eu/rsa).
+        
+        Download and install using:
+        
+            pip install rsa
+        
+        or download it from the [Python Package Index](https://pypi.org/project/rsa/).
+        
+        The source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is
+        licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
+        
+        
+        Major changes in 4.0
+        --------------------
+        
+        Version 3.4 was the last version in the 3.x range. Version 4.0 drops the following modules,
+        as they are insecure:
+        
+        - `rsa._version133`
+        - `rsa._version200`
+        - `rsa.bigfile`
+        - `rsa.varblock`
+        
+        Those modules were marked as deprecated in version 3.4.
+        
+        Furthermore, in 4.0 the I/O functions is streamlined to always work with bytes on all
+        supported versions of Python.
+        
+        Version 4.0 drops support for Python 2.6 and 3.3.
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: Intended Audience :: Information Technology
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Security :: Cryptography
+Description-Content-Type: text/markdown

+ 12 - 13
desktop/core/ext-py/rsa-3.4.2/README.md → desktop/core/ext-py/rsa-4.0/README.md

@@ -1,13 +1,10 @@
 Pure Python RSA implementation
 Pure Python RSA implementation
 ==============================
 ==============================
 
 
-[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.python.org/pypi/rsa)
-[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)]
-    (https://travis-ci.org/sybrenstuvel/python-rsa)
-[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)]
-    (https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master)
-[![Code Climate](https://img.shields.io/codeclimate/github/sybrenstuvel/python-rsa.svg)]
-    (https://codeclimate.com/github/sybrenstuvel/python-rsa)
+[![PyPI](https://img.shields.io/pypi/v/rsa.svg)](https://pypi.org/project/rsa/)
+[![Build Status](https://travis-ci.org/sybrenstuvel/python-rsa.svg?branch=master)](https://travis-ci.org/sybrenstuvel/python-rsa)
+[![Coverage Status](https://coveralls.io/repos/github/sybrenstuvel/python-rsa/badge.svg?branch=master)](https://coveralls.io/github/sybrenstuvel/python-rsa?branch=master)
+[![Code Climate](https://img.shields.io/codeclimate/github/sybrenstuvel/python-rsa.svg)](https://codeclimate.com/github/sybrenstuvel/python-rsa)
 
 
 [Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports
 [Python-RSA](https://stuvel.eu/rsa) is a pure-Python RSA implementation. It supports
 encryption and decryption, signing and verifying signatures, and key
 encryption and decryption, signing and verifying signatures, and key
@@ -21,16 +18,16 @@ Download and install using:
 
 
     pip install rsa
     pip install rsa
 
 
-or download it from the [Python Package Index](https://pypi.python.org/pypi/rsa).
+or download it from the [Python Package Index](https://pypi.org/project/rsa/).
 
 
-The source code is maintained at [Github](https://github.com/sybrenstuvel/python-rsa/) and is
+The source code is maintained at [GitHub](https://github.com/sybrenstuvel/python-rsa/) and is
 licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
 licensed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
 
 
 
 
-Plans for the future
+Major changes in 4.0
 --------------------
 --------------------
 
 
-Version 3.4 is the last version in the 3.x range. Version 4.0 will drop the following modules,
+Version 3.4 was the last version in the 3.x range. Version 4.0 drops the following modules,
 as they are insecure:
 as they are insecure:
 
 
 - `rsa._version133`
 - `rsa._version133`
@@ -38,7 +35,9 @@ as they are insecure:
 - `rsa.bigfile`
 - `rsa.bigfile`
 - `rsa.varblock`
 - `rsa.varblock`
 
 
-Those modules are marked as deprecated in version 3.4.
+Those modules were marked as deprecated in version 3.4.
 
 
-Furthermore, in 4.0 the I/O functions will be streamlined to always work with bytes on all
+Furthermore, in 4.0 the I/O functions is streamlined to always work with bytes on all
 supported versions of Python.
 supported versions of Python.
+
+Version 4.0 drops support for Python 2.6 and 3.3.

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/create_timing_table.py → desktop/core/ext-py/rsa-4.0/create_timing_table.py


+ 7 - 7
desktop/core/ext-py/rsa-3.4.2/rsa/__init__.py → desktop/core/ext-py/rsa-4.0/rsa/__init__.py

@@ -18,19 +18,18 @@
 Module for calculating large primes, and RSA encryption, decryption, signing
 Module for calculating large primes, and RSA encryption, decryption, signing
 and verification. Includes generating public and private keys.
 and verification. Includes generating public and private keys.
 
 
-WARNING: this implementation does not use random padding, compression of the
-cleartext input to prevent repetitions, or other common security improvements.
-Use with care.
+WARNING: this implementation does not use compression of the cleartext input to
+prevent repetitions, or other common security improvements. Use with care.
 
 
 """
 """
 
 
 from rsa.key import newkeys, PrivateKey, PublicKey
 from rsa.key import newkeys, PrivateKey, PublicKey
 from rsa.pkcs1 import encrypt, decrypt, sign, verify, DecryptionError, \
 from rsa.pkcs1 import encrypt, decrypt, sign, verify, DecryptionError, \
-    VerificationError
+    VerificationError, find_signature_hash,  sign_hash, compute_hash
 
 
 __author__ = "Sybren Stuvel, Barry Mead and Yesudeep Mangalapilly"
 __author__ = "Sybren Stuvel, Barry Mead and Yesudeep Mangalapilly"
-__date__ = "2016-03-29"
-__version__ = '3.4.2'
+__date__ = "2018-09-16"
+__version__ = '4.0'
 
 
 # Do doctest if we're run directly
 # Do doctest if we're run directly
 if __name__ == "__main__":
 if __name__ == "__main__":
@@ -39,4 +38,5 @@ if __name__ == "__main__":
     doctest.testmod()
     doctest.testmod()
 
 
 __all__ = ["newkeys", "encrypt", "decrypt", "sign", "verify", 'PublicKey',
 __all__ = ["newkeys", "encrypt", "decrypt", "sign", "verify", 'PublicKey',
-           'PrivateKey', 'DecryptionError', 'VerificationError']
+           'PrivateKey', 'DecryptionError', 'VerificationError',
+           'compute_hash', 'sign_hash']

+ 41 - 27
desktop/core/ext-py/rsa-3.4.2/rsa/_compat.py → desktop/core/ext-py/rsa-4.0/rsa/_compat.py

@@ -18,18 +18,17 @@
 
 
 from __future__ import absolute_import
 from __future__ import absolute_import
 
 
+import itertools
 import sys
 import sys
 from struct import pack
 from struct import pack
 
 
-try:
-    MAX_INT = sys.maxsize
-except AttributeError:
-    MAX_INT = sys.maxint
-
+MAX_INT = sys.maxsize
 MAX_INT64 = (1 << 63) - 1
 MAX_INT64 = (1 << 63) - 1
 MAX_INT32 = (1 << 31) - 1
 MAX_INT32 = (1 << 31) - 1
 MAX_INT16 = (1 << 15) - 1
 MAX_INT16 = (1 << 15) - 1
 
 
+PY2 = sys.version_info[0] == 2
+
 # Determine the word size of the processor.
 # Determine the word size of the processor.
 if MAX_INT == MAX_INT64:
 if MAX_INT == MAX_INT64:
     # 64-bit processor.
     # 64-bit processor.
@@ -41,32 +40,26 @@ else:
     # Else we just assume 64-bit processor keeping up with modern times.
     # Else we just assume 64-bit processor keeping up with modern times.
     MACHINE_WORD_SIZE = 64
     MACHINE_WORD_SIZE = 64
 
 
-try:
-    # < Python3
-    unicode_type = unicode
-except NameError:
-    # Python3.
-    unicode_type = str
-
-# Fake byte literals.
-if str is unicode_type:
-    def byte_literal(s):
-        return s.encode('latin1')
+if PY2:
+    integer_types = (int, long)
+    range = xrange
+    zip = itertools.izip
 else:
 else:
-    def byte_literal(s):
-        return s
+    integer_types = (int, )
+    range = range
+    zip = zip
 
 
-# ``long`` is no more. Do type detection using this instead.
-try:
-    integer_types = (int, long)
-except NameError:
-    integer_types = (int,)
 
 
-b = byte_literal
+def write_to_stdout(data):
+    """Writes bytes to stdout
 
 
-# To avoid calling b() multiple times in tight loops.
-ZERO_BYTE = b('\x00')
-EMPTY_BYTE = b('')
+    :type data: bytes
+    """
+    if PY2:
+        sys.stdout.write(data)
+    else:
+        # On Py3 we must use the buffer interface to write bytes.
+        sys.stdout.buffer.write(data)
 
 
 
 
 def is_bytes(obj):
 def is_bytes(obj):
@@ -109,6 +102,27 @@ def byte(num):
     return pack("B", num)
     return pack("B", num)
 
 
 
 
+def xor_bytes(b1, b2):
+    """
+    Returns the bitwise XOR result between two bytes objects, b1 ^ b2.
+
+    Bitwise XOR operation is commutative, so order of parameters doesn't
+    generate different results. If parameters have different length, extra
+    length of the largest one is ignored.
+
+    :param b1:
+        First bytes object.
+    :param b2:
+        Second bytes object.
+    :returns:
+        Bytes object, result of XOR operation.
+    """
+    if PY2:
+        return ''.join(byte(ord(x) ^ ord(y)) for x, y in zip(b1, b2))
+
+    return bytes(x ^ y for x, y in zip(b1, b2))
+
+
 def get_word_alignment(num, force_arch=64,
 def get_word_alignment(num, force_arch=64,
                        _machine_word_size=MACHINE_WORD_SIZE):
                        _machine_word_size=MACHINE_WORD_SIZE):
     """
     """

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/rsa/asn1.py → desktop/core/ext-py/rsa-4.0/rsa/asn1.py


+ 5 - 100
desktop/core/ext-py/rsa-3.4.2/rsa/cli.py → desktop/core/ext-py/rsa-4.0/rsa/cli.py

@@ -26,7 +26,6 @@ import sys
 from optparse import OptionParser
 from optparse import OptionParser
 
 
 import rsa
 import rsa
-import rsa.bigfile
 import rsa.pkcs1
 import rsa.pkcs1
 
 
 HASH_METHODS = sorted(rsa.pkcs1.HASH_METHODS.keys())
 HASH_METHODS = sorted(rsa.pkcs1.HASH_METHODS.keys())
@@ -84,7 +83,7 @@ def keygen():
             outfile.write(data)
             outfile.write(data)
     else:
     else:
         print('Writing private key to stdout', file=sys.stderr)
         print('Writing private key to stdout', file=sys.stderr)
-        sys.stdout.write(data)
+        rsa._compat.write_to_stdout(data)
 
 
 
 
 class CryptoOperation(object):
 class CryptoOperation(object):
@@ -113,7 +112,7 @@ class CryptoOperation(object):
         self.output_help = self.output_help % self.__class__.__dict__
         self.output_help = self.output_help % self.__class__.__dict__
 
 
     @abc.abstractmethod
     @abc.abstractmethod
-    def perform_operation(self, indata, key, cli_args=None):
+    def perform_operation(self, indata, key, cli_args):
         """Performs the program's operation.
         """Performs the program's operation.
 
 
         Implement in a subclass.
         Implement in a subclass.
@@ -190,7 +189,7 @@ class CryptoOperation(object):
                 outfile.write(outdata)
                 outfile.write(outdata)
         else:
         else:
             print('Writing output to stdout', file=sys.stderr)
             print('Writing output to stdout', file=sys.stderr)
-            sys.stdout.write(outdata)
+            rsa._compat.write_to_stdout(outdata)
 
 
 
 
 class EncryptOperation(CryptoOperation):
 class EncryptOperation(CryptoOperation):
@@ -198,8 +197,7 @@ class EncryptOperation(CryptoOperation):
 
 
     keyname = 'public'
     keyname = 'public'
     description = ('Encrypts a file. The file must be shorter than the key '
     description = ('Encrypts a file. The file must be shorter than the key '
-                   'length in order to be encrypted. For larger files, use the '
-                   'pyrsa-encrypt-bigfile command.')
+                   'length in order to be encrypted.')
     operation = 'encrypt'
     operation = 'encrypt'
     operation_past = 'encrypted'
     operation_past = 'encrypted'
     operation_progressive = 'encrypting'
     operation_progressive = 'encrypting'
@@ -215,8 +213,7 @@ class DecryptOperation(CryptoOperation):
 
 
     keyname = 'private'
     keyname = 'private'
     description = ('Decrypts a file. The original file must be shorter than '
     description = ('Decrypts a file. The original file must be shorter than '
-                   'the key length in order to have been encrypted. For larger '
-                   'files, use the pyrsa-decrypt-bigfile command.')
+                   'the key length in order to have been encrypted.')
     operation = 'decrypt'
     operation = 'decrypt'
     operation_past = 'decrypted'
     operation_past = 'decrypted'
     operation_progressive = 'decrypting'
     operation_progressive = 'decrypting'
@@ -285,99 +282,7 @@ class VerifyOperation(CryptoOperation):
         print('Verification OK', file=sys.stderr)
         print('Verification OK', file=sys.stderr)
 
 
 
 
-class BigfileOperation(CryptoOperation):
-    """CryptoOperation that doesn't read the entire file into memory."""
-
-    def __init__(self):
-        CryptoOperation.__init__(self)
-
-        self.file_objects = []
-
-    def __del__(self):
-        """Closes any open file handles."""
-
-        for fobj in self.file_objects:
-            fobj.close()
-
-    def __call__(self):
-        """Runs the program."""
-
-        (cli, cli_args) = self.parse_cli()
-
-        key = self.read_key(cli_args[0], cli.keyform)
-
-        # Get the file handles
-        infile = self.get_infile(cli.input)
-        outfile = self.get_outfile(cli.output)
-
-        # Call the operation
-        print(self.operation_progressive.title(), file=sys.stderr)
-        self.perform_operation(infile, outfile, key, cli_args)
-
-    def get_infile(self, inname):
-        """Returns the input file object"""
-
-        if inname:
-            print('Reading input from %s' % inname, file=sys.stderr)
-            fobj = open(inname, 'rb')
-            self.file_objects.append(fobj)
-        else:
-            print('Reading input from stdin', file=sys.stderr)
-            fobj = sys.stdin
-
-        return fobj
-
-    def get_outfile(self, outname):
-        """Returns the output file object"""
-
-        if outname:
-            print('Will write output to %s' % outname, file=sys.stderr)
-            fobj = open(outname, 'wb')
-            self.file_objects.append(fobj)
-        else:
-            print('Will write output to stdout', file=sys.stderr)
-            fobj = sys.stdout
-
-        return fobj
-
-
-class EncryptBigfileOperation(BigfileOperation):
-    """Encrypts a file to VARBLOCK format."""
-
-    keyname = 'public'
-    description = ('Encrypts a file to an encrypted VARBLOCK file. The file '
-                   'can be larger than the key length, but the output file is only '
-                   'compatible with Python-RSA.')
-    operation = 'encrypt'
-    operation_past = 'encrypted'
-    operation_progressive = 'encrypting'
-
-    def perform_operation(self, infile, outfile, pub_key, cli_args=None):
-        """Encrypts files to VARBLOCK."""
-
-        return rsa.bigfile.encrypt_bigfile(infile, outfile, pub_key)
-
-
-class DecryptBigfileOperation(BigfileOperation):
-    """Decrypts a file in VARBLOCK format."""
-
-    keyname = 'private'
-    description = ('Decrypts an encrypted VARBLOCK file that was encrypted '
-                   'with pyrsa-encrypt-bigfile')
-    operation = 'decrypt'
-    operation_past = 'decrypted'
-    operation_progressive = 'decrypting'
-    key_class = rsa.PrivateKey
-
-    def perform_operation(self, infile, outfile, priv_key, cli_args=None):
-        """Decrypts a VARBLOCK file."""
-
-        return rsa.bigfile.decrypt_bigfile(infile, outfile, priv_key)
-
-
 encrypt = EncryptOperation()
 encrypt = EncryptOperation()
 decrypt = DecryptOperation()
 decrypt = DecryptOperation()
 sign = SignOperation()
 sign = SignOperation()
 verify = VerifyOperation()
 verify = VerifyOperation()
-encrypt_bigfile = EncryptBigfileOperation()
-decrypt_bigfile = DecryptBigfileOperation()

+ 42 - 42
desktop/core/ext-py/rsa-3.4.2/rsa/common.py → desktop/core/ext-py/rsa-4.0/rsa/common.py

@@ -14,17 +14,25 @@
 #  See the License for the specific language governing permissions and
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 #  limitations under the License.
 
 
+from rsa._compat import zip
+
 """Common functionality shared by several modules."""
 """Common functionality shared by several modules."""
 
 
 
 
+class NotRelativePrimeError(ValueError):
+    def __init__(self, a, b, d, msg=None):
+        super(NotRelativePrimeError, self).__init__(
+            msg or "%d and %d are not relatively prime, divider=%i" % (a, b, d))
+        self.a = a
+        self.b = b
+        self.d = d
+
+
 def bit_size(num):
 def bit_size(num):
     """
     """
     Number of bits needed to represent a integer excluding any prefix
     Number of bits needed to represent a integer excluding any prefix
     0 bits.
     0 bits.
 
 
-    As per definition from https://wiki.python.org/moin/BitManipulation and
-    to match the behavior of the Python 3 API.
-
     Usage::
     Usage::
 
 
         >>> bit_size(1023)
         >>> bit_size(1023)
@@ -41,41 +49,11 @@ def bit_size(num):
     :returns:
     :returns:
         Returns the number of bits in the integer.
         Returns the number of bits in the integer.
     """
     """
-    if num == 0:
-        return 0
-    if num < 0:
-        num = -num
-
-    # Make sure this is an int and not a float.
-    num & 1
-
-    hex_num = "%x" % num
-    return ((len(hex_num) - 1) * 4) + {
-        '0': 0, '1': 1, '2': 2, '3': 2,
-        '4': 3, '5': 3, '6': 3, '7': 3,
-        '8': 4, '9': 4, 'a': 4, 'b': 4,
-        'c': 4, 'd': 4, 'e': 4, 'f': 4,
-    }[hex_num[0]]
-
-
-def _bit_size(number):
-    """
-    Returns the number of bits required to hold a specific long number.
-    """
-    if number < 0:
-        raise ValueError('Only nonnegative numbers possible: %s' % number)
-
-    if number == 0:
-        return 0
 
 
-    # This works, even with very large numbers. When using math.log(number, 2),
-    # you'll get rounding errors and it'll fail.
-    bits = 0
-    while number:
-        bits += 1
-        number >>= 1
-
-    return bits
+    try:
+        return num.bit_length()
+    except AttributeError:
+        raise TypeError('bit_size(num) only supports integers, not %r' % type(num))
 
 
 
 
 def byte_size(number):
 def byte_size(number):
@@ -98,11 +76,33 @@ def byte_size(number):
     :returns:
     :returns:
         The number of bytes required to hold a specific long number.
         The number of bytes required to hold a specific long number.
     """
     """
-    quanta, mod = divmod(bit_size(number), 8)
-    if mod or number == 0:
+    if number == 0:
+        return 1
+    return ceil_div(bit_size(number), 8)
+
+
+def ceil_div(num, div):
+    """
+    Returns the ceiling function of a division between `num` and `div`.
+
+    Usage::
+
+        >>> ceil_div(100, 7)
+        15
+        >>> ceil_div(100, 10)
+        10
+        >>> ceil_div(1, 4)
+        1
+
+    :param num: Division's numerator, a number
+    :param div: Division's divisor, a number
+
+    :return: Rounded up result of the division between the parameters.
+    """
+    quanta, mod = divmod(num, div)
+    if mod:
         quanta += 1
         quanta += 1
     return quanta
     return quanta
-    # return int(math.ceil(bit_size(number) / 8.0))
 
 
 
 
 def extended_gcd(a, b):
 def extended_gcd(a, b):
@@ -131,7 +131,7 @@ def extended_gcd(a, b):
 
 
 
 
 def inverse(x, n):
 def inverse(x, n):
-    """Returns x^-1 (mod n)
+    """Returns the inverse of x % n under multiplication, a.k.a x^-1 (mod n)
 
 
     >>> inverse(7, 4)
     >>> inverse(7, 4)
     3
     3
@@ -142,7 +142,7 @@ def inverse(x, n):
     (divider, inv, _) = extended_gcd(x, n)
     (divider, inv, _) = extended_gcd(x, n)
 
 
     if divider != 1:
     if divider != 1:
-        raise ValueError("x (%d) and n (%d) are not relatively prime" % (x, n))
+        raise NotRelativePrimeError(x, n, divider)
 
 
     return inv
     return inv
 
 

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/rsa/core.py → desktop/core/ext-py/rsa-4.0/rsa/core.py


+ 108 - 56
desktop/core/ext-py/rsa-3.4.2/rsa/key.py → desktop/core/ext-py/rsa-4.0/rsa/key.py

@@ -34,14 +34,16 @@ of pyasn1.
 """
 """
 
 
 import logging
 import logging
-from rsa._compat import b
+import warnings
 
 
+from rsa._compat import range
 import rsa.prime
 import rsa.prime
 import rsa.pem
 import rsa.pem
 import rsa.common
 import rsa.common
 import rsa.randnum
 import rsa.randnum
 import rsa.core
 import rsa.core
 
 
+
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 DEFAULT_EXPONENT = 65537
 DEFAULT_EXPONENT = 65537
 
 
@@ -55,15 +57,56 @@ class AbstractKey(object):
         self.n = n
         self.n = n
         self.e = e
         self.e = e
 
 
+    @classmethod
+    def _load_pkcs1_pem(cls, keyfile):
+        """Loads a key in PKCS#1 PEM format, implement in a subclass.
+
+        :param keyfile: contents of a PEM-encoded file that contains
+            the public key.
+        :type keyfile: bytes
+
+        :return: the loaded key
+        :rtype: AbstractKey
+        """
+
+    @classmethod
+    def _load_pkcs1_der(cls, keyfile):
+        """Loads a key in PKCS#1 PEM format, implement in a subclass.
+
+        :param keyfile: contents of a DER-encoded file that contains
+            the public key.
+        :type keyfile: bytes
+
+        :return: the loaded key
+        :rtype: AbstractKey
+        """
+
+    def _save_pkcs1_pem(self):
+        """Saves the key in PKCS#1 PEM format, implement in a subclass.
+
+        :returns: the PEM-encoded key.
+        :rtype: bytes
+        """
+
+    def _save_pkcs1_der(self):
+        """Saves the key in PKCS#1 DER format, implement in a subclass.
+
+        :returns: the DER-encoded key.
+        :rtype: bytes
+        """
+
     @classmethod
     @classmethod
     def load_pkcs1(cls, keyfile, format='PEM'):
     def load_pkcs1(cls, keyfile, format='PEM'):
         """Loads a key in PKCS#1 DER or PEM format.
         """Loads a key in PKCS#1 DER or PEM format.
 
 
         :param keyfile: contents of a DER- or PEM-encoded file that contains
         :param keyfile: contents of a DER- or PEM-encoded file that contains
-            the public key.
+            the key.
+        :type keyfile: bytes
         :param format: the format of the file to load; 'PEM' or 'DER'
         :param format: the format of the file to load; 'PEM' or 'DER'
+        :type format: str
 
 
-        :return: a PublicKey object
+        :return: the loaded key
+        :rtype: AbstractKey
         """
         """
 
 
         methods = {
         methods = {
@@ -87,10 +130,12 @@ class AbstractKey(object):
                                                                         formats))
                                                                         formats))
 
 
     def save_pkcs1(self, format='PEM'):
     def save_pkcs1(self, format='PEM'):
-        """Saves the public key in PKCS#1 DER or PEM format.
+        """Saves the key in PKCS#1 DER or PEM format.
 
 
         :param format: the format to save; 'PEM' or 'DER'
         :param format: the format to save; 'PEM' or 'DER'
-        :returns: the DER- or PEM-encoded public key.
+        :type format: str
+        :returns: the DER- or PEM-encoded key.
+        :rtype: bytes
         """
         """
 
 
         methods = {
         methods = {
@@ -139,7 +184,7 @@ class PublicKey(AbstractKey):
     This key is also known as the 'encryption key'. It contains the 'n' and 'e'
     This key is also known as the 'encryption key'. It contains the 'n' and 'e'
     values.
     values.
 
 
-    Supports attributes as well as dictionary-like access. Attribute accesss is
+    Supports attributes as well as dictionary-like access. Attribute access is
     faster, though.
     faster, though.
 
 
     >>> PublicKey(5, 3)
     >>> PublicKey(5, 3)
@@ -185,6 +230,9 @@ class PublicKey(AbstractKey):
     def __ne__(self, other):
     def __ne__(self, other):
         return not (self == other)
         return not (self == other)
 
 
+    def __hash__(self):
+        return hash((self.n, self.e))
+
     @classmethod
     @classmethod
     def _load_pkcs1_der(cls, keyfile):
     def _load_pkcs1_der(cls, keyfile):
         """Loads a key in PKCS#1 DER format.
         """Loads a key in PKCS#1 DER format.
@@ -215,7 +263,8 @@ class PublicKey(AbstractKey):
     def _save_pkcs1_der(self):
     def _save_pkcs1_der(self):
         """Saves the public key in PKCS#1 DER format.
         """Saves the public key in PKCS#1 DER format.
 
 
-        @returns: the DER-encoded public key.
+        :returns: the DER-encoded public key.
+        :rtype: bytes
         """
         """
 
 
         from pyasn1.codec.der import encoder
         from pyasn1.codec.der import encoder
@@ -247,6 +296,7 @@ class PublicKey(AbstractKey):
         """Saves a PKCS#1 PEM-encoded public key file.
         """Saves a PKCS#1 PEM-encoded public key file.
 
 
         :return: contents of a PEM-encoded file that contains the public key.
         :return: contents of a PEM-encoded file that contains the public key.
+        :rtype: bytes
         """
         """
 
 
         der = self._save_pkcs1_der()
         der = self._save_pkcs1_der()
@@ -264,6 +314,7 @@ class PublicKey(AbstractKey):
 
 
         :param keyfile: contents of a PEM-encoded file that contains the public
         :param keyfile: contents of a PEM-encoded file that contains the public
             key, from OpenSSL.
             key, from OpenSSL.
+        :type keyfile: bytes
         :return: a PublicKey object
         :return: a PublicKey object
         """
         """
 
 
@@ -277,6 +328,7 @@ class PublicKey(AbstractKey):
         :param keyfile: contents of a DER-encoded file that contains the public
         :param keyfile: contents of a DER-encoded file that contains the public
             key, from OpenSSL.
             key, from OpenSSL.
         :return: a PublicKey object
         :return: a PublicKey object
+        :rtype: bytes
 
 
         """
         """
 
 
@@ -298,57 +350,36 @@ class PrivateKey(AbstractKey):
     This key is also known as the 'decryption key'. It contains the 'n', 'e',
     This key is also known as the 'decryption key'. It contains the 'n', 'e',
     'd', 'p', 'q' and other values.
     'd', 'p', 'q' and other values.
 
 
-    Supports attributes as well as dictionary-like access. Attribute accesss is
+    Supports attributes as well as dictionary-like access. Attribute access is
     faster, though.
     faster, though.
 
 
     >>> PrivateKey(3247, 65537, 833, 191, 17)
     >>> PrivateKey(3247, 65537, 833, 191, 17)
     PrivateKey(3247, 65537, 833, 191, 17)
     PrivateKey(3247, 65537, 833, 191, 17)
 
 
-    exp1, exp2 and coef can be given, but if None or omitted they will be calculated:
+    exp1, exp2 and coef will be calculated:
 
 
-    >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287, exp2=4)
+    >>> pk = PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
     >>> pk.exp1
     >>> pk.exp1
     55063
     55063
-    >>> pk.exp2  # this is of course not a correct value, but it is the one we passed.
-    4
-    >>> pk.coef
-    50797
-
-    If you give exp1, exp2 or coef, they will be used as-is:
-
-    >>> pk = PrivateKey(1, 2, 3, 4, 5, 6, 7, 8)
-    >>> pk.exp1
-    6
     >>> pk.exp2
     >>> pk.exp2
-    7
+    10095
     >>> pk.coef
     >>> pk.coef
-    8
+    50797
 
 
     """
     """
 
 
     __slots__ = ('n', 'e', 'd', 'p', 'q', 'exp1', 'exp2', 'coef')
     __slots__ = ('n', 'e', 'd', 'p', 'q', 'exp1', 'exp2', 'coef')
 
 
-    def __init__(self, n, e, d, p, q, exp1=None, exp2=None, coef=None):
+    def __init__(self, n, e, d, p, q):
         AbstractKey.__init__(self, n, e)
         AbstractKey.__init__(self, n, e)
         self.d = d
         self.d = d
         self.p = p
         self.p = p
         self.q = q
         self.q = q
 
 
-        # Calculate the other values if they aren't supplied
-        if exp1 is None:
-            self.exp1 = int(d % (p - 1))
-        else:
-            self.exp1 = exp1
-
-        if exp2 is None:
-            self.exp2 = int(d % (q - 1))
-        else:
-            self.exp2 = exp2
-
-        if coef is None:
-            self.coef = rsa.common.inverse(q, p)
-        else:
-            self.coef = coef
+        # Calculate exponents and coefficient.
+        self.exp1 = int(d % (p - 1))
+        self.exp2 = int(d % (q - 1))
+        self.coef = rsa.common.inverse(q, p)
 
 
     def __getitem__(self, key):
     def __getitem__(self, key):
         return getattr(self, key)
         return getattr(self, key)
@@ -383,6 +414,9 @@ class PrivateKey(AbstractKey):
     def __ne__(self, other):
     def __ne__(self, other):
         return not (self == other)
         return not (self == other)
 
 
+    def __hash__(self):
+        return hash((self.n, self.e, self.d, self.p, self.q, self.exp1, self.exp2, self.coef))
+
     def blinded_decrypt(self, encrypted):
     def blinded_decrypt(self, encrypted):
         """Decrypts the message using blinding to prevent side-channel attacks.
         """Decrypts the message using blinding to prevent side-channel attacks.
 
 
@@ -420,6 +454,7 @@ class PrivateKey(AbstractKey):
 
 
         :param keyfile: contents of a DER-encoded file that contains the private
         :param keyfile: contents of a DER-encoded file that contains the private
             key.
             key.
+        :type keyfile: bytes
         :return: a PrivateKey object
         :return: a PrivateKey object
 
 
         First let's construct a DER encoded key:
         First let's construct a DER encoded key:
@@ -456,13 +491,26 @@ class PrivateKey(AbstractKey):
         if priv[0] != 0:
         if priv[0] != 0:
             raise ValueError('Unable to read this file, version %s != 0' % priv[0])
             raise ValueError('Unable to read this file, version %s != 0' % priv[0])
 
 
-        as_ints = tuple(int(x) for x in priv[1:9])
-        return cls(*as_ints)
+        as_ints = map(int, priv[1:6])
+        key = cls(*as_ints)
+
+        exp1, exp2, coef = map(int, priv[6:9])
+
+        if (key.exp1, key.exp2, key.coef) != (exp1, exp2, coef):
+            warnings.warn(
+                'You have provided a malformed keyfile. Either the exponents '
+                'or the coefficient are incorrect. Using the correct values '
+                'instead.',
+                UserWarning,
+            )
+
+        return key
 
 
     def _save_pkcs1_der(self):
     def _save_pkcs1_der(self):
         """Saves the private key in PKCS#1 DER format.
         """Saves the private key in PKCS#1 DER format.
 
 
-        @returns: the DER-encoded private key.
+        :returns: the DER-encoded private key.
+        :rtype: bytes
         """
         """
 
 
         from pyasn1.type import univ, namedtype
         from pyasn1.type import univ, namedtype
@@ -470,15 +518,15 @@ class PrivateKey(AbstractKey):
 
 
         class AsnPrivKey(univ.Sequence):
         class AsnPrivKey(univ.Sequence):
             componentType = namedtype.NamedTypes(
             componentType = namedtype.NamedTypes(
-                    namedtype.NamedType('version', univ.Integer()),
-                    namedtype.NamedType('modulus', univ.Integer()),
-                    namedtype.NamedType('publicExponent', univ.Integer()),
-                    namedtype.NamedType('privateExponent', univ.Integer()),
-                    namedtype.NamedType('prime1', univ.Integer()),
-                    namedtype.NamedType('prime2', univ.Integer()),
-                    namedtype.NamedType('exponent1', univ.Integer()),
-                    namedtype.NamedType('exponent2', univ.Integer()),
-                    namedtype.NamedType('coefficient', univ.Integer()),
+                namedtype.NamedType('version', univ.Integer()),
+                namedtype.NamedType('modulus', univ.Integer()),
+                namedtype.NamedType('publicExponent', univ.Integer()),
+                namedtype.NamedType('privateExponent', univ.Integer()),
+                namedtype.NamedType('prime1', univ.Integer()),
+                namedtype.NamedType('prime2', univ.Integer()),
+                namedtype.NamedType('exponent1', univ.Integer()),
+                namedtype.NamedType('exponent2', univ.Integer()),
+                namedtype.NamedType('coefficient', univ.Integer()),
             )
             )
 
 
         # Create the ASN object
         # Create the ASN object
@@ -504,20 +552,22 @@ class PrivateKey(AbstractKey):
 
 
         :param keyfile: contents of a PEM-encoded file that contains the private
         :param keyfile: contents of a PEM-encoded file that contains the private
             key.
             key.
+        :type keyfile: bytes
         :return: a PrivateKey object
         :return: a PrivateKey object
         """
         """
 
 
-        der = rsa.pem.load_pem(keyfile, b('RSA PRIVATE KEY'))
+        der = rsa.pem.load_pem(keyfile, b'RSA PRIVATE KEY')
         return cls._load_pkcs1_der(der)
         return cls._load_pkcs1_der(der)
 
 
     def _save_pkcs1_pem(self):
     def _save_pkcs1_pem(self):
         """Saves a PKCS#1 PEM-encoded private key file.
         """Saves a PKCS#1 PEM-encoded private key file.
 
 
         :return: contents of a PEM-encoded file that contains the private key.
         :return: contents of a PEM-encoded file that contains the private key.
+        :rtype: bytes
         """
         """
 
 
         der = self._save_pkcs1_der()
         der = self._save_pkcs1_der()
-        return rsa.pem.save_pem(der, b('RSA PRIVATE KEY'))
+        return rsa.pem.save_pem(der, b'RSA PRIVATE KEY')
 
 
 
 
 def find_p_q(nbits, getprime_func=rsa.prime.getprime, accurate=True):
 def find_p_q(nbits, getprime_func=rsa.prime.getprime, accurate=True):
@@ -615,9 +665,11 @@ def calculate_keys_custom_exponent(p, q, exponent):
 
 
     try:
     try:
         d = rsa.common.inverse(exponent, phi_n)
         d = rsa.common.inverse(exponent, phi_n)
-    except ValueError:
-        raise ValueError("e (%d) and phi_n (%d) are not relatively prime" %
-                         (exponent, phi_n))
+    except rsa.common.NotRelativePrimeError as ex:
+        raise rsa.common.NotRelativePrimeError(
+            exponent, phi_n, ex.d,
+            msg="e (%d) and phi_n (%d) are not relatively prime (divider=%i)" %
+                (exponent, phi_n, ex.d))
 
 
     if (exponent * d) % phi_n != 1:
     if (exponent * d) % phi_n != 1:
         raise ValueError("e (%d) and d (%d) are not mult. inv. modulo "
         raise ValueError("e (%d) and d (%d) are not mult. inv. modulo "
@@ -731,7 +783,7 @@ if __name__ == '__main__':
             if failures:
             if failures:
                 break
                 break
 
 
-            if (count and count % 10 == 0) or count == 1:
+            if (count % 10 == 0 and count) or count == 1:
                 print('%i times' % count)
                 print('%i times' % count)
     except KeyboardInterrupt:
     except KeyboardInterrupt:
         print('Aborted')
         print('Aborted')

+ 74 - 0
desktop/core/ext-py/rsa-4.0/rsa/machine_size.py

@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+#
+#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+"""Detection of 32-bit and 64-bit machines and byte alignment."""
+
+import sys
+
+MAX_INT = sys.maxsize
+MAX_INT64 = (1 << 63) - 1
+MAX_INT32 = (1 << 31) - 1
+MAX_INT16 = (1 << 15) - 1
+
+# Determine the word size of the processor.
+if MAX_INT == MAX_INT64:
+    # 64-bit processor.
+    MACHINE_WORD_SIZE = 64
+elif MAX_INT == MAX_INT32:
+    # 32-bit processor.
+    MACHINE_WORD_SIZE = 32
+else:
+    # Else we just assume 64-bit processor keeping up with modern times.
+    MACHINE_WORD_SIZE = 64
+
+
+def get_word_alignment(num, force_arch=64,
+                       _machine_word_size=MACHINE_WORD_SIZE):
+    """
+    Returns alignment details for the given number based on the platform
+    Python is running on.
+
+    :param num:
+        Unsigned integral number.
+    :param force_arch:
+        If you don't want to use 64-bit unsigned chunks, set this to
+        anything other than 64. 32-bit chunks will be preferred then.
+        Default 64 will be used when on a 64-bit machine.
+    :param _machine_word_size:
+        (Internal) The machine word size used for alignment.
+    :returns:
+        4-tuple::
+
+            (word_bits, word_bytes,
+             max_uint, packing_format_type)
+    """
+    max_uint64 = 0xffffffffffffffff
+    max_uint32 = 0xffffffff
+    max_uint16 = 0xffff
+    max_uint8 = 0xff
+
+    if force_arch == 64 and _machine_word_size >= 64 and num > max_uint32:
+        # 64-bit unsigned integer.
+        return 64, 8, max_uint64, "Q"
+    elif num > max_uint16:
+        # 32-bit unsigned integer
+        return 32, 4, max_uint32, "L"
+    elif num > max_uint8:
+        # 16-bit unsigned integer.
+        return 16, 2, max_uint16, "H"
+    else:
+        # 8-bit unsigned integer.
+        return 8, 1, max_uint8, "B"

+ 2 - 1
desktop/core/ext-py/rsa-3.4.2/rsa/parallel.py → desktop/core/ext-py/rsa-4.0/rsa/parallel.py

@@ -28,6 +28,7 @@ from __future__ import print_function
 
 
 import multiprocessing as mp
 import multiprocessing as mp
 
 
+from rsa._compat import range
 import rsa.prime
 import rsa.prime
 import rsa.randnum
 import rsa.randnum
 
 
@@ -94,7 +95,7 @@ if __name__ == '__main__':
         if failures:
         if failures:
             break
             break
 
 
-        if count and count % 10 == 0:
+        if count % 10 == 0 and count:
             print('%i times' % count)
             print('%i times' % count)
 
 
     print('Doctests done')
     print('Doctests done')

+ 13 - 12
desktop/core/ext-py/rsa-3.4.2/rsa/pem.py → desktop/core/ext-py/rsa-4.0/rsa/pem.py

@@ -17,19 +17,20 @@
 """Functions that load and write PEM-encoded files."""
 """Functions that load and write PEM-encoded files."""
 
 
 import base64
 import base64
-from rsa._compat import b, is_bytes
+
+from rsa._compat import is_bytes, range
 
 
 
 
 def _markers(pem_marker):
 def _markers(pem_marker):
     """
     """
-    Returns the start and end PEM markers
+    Returns the start and end PEM markers, as bytes.
     """
     """
 
 
-    if is_bytes(pem_marker):
-        pem_marker = pem_marker.decode('utf-8')
+    if not is_bytes(pem_marker):
+        pem_marker = pem_marker.encode('ascii')
 
 
-    return (b('-----BEGIN %s-----' % pem_marker),
-            b('-----END %s-----' % pem_marker))
+    return (b'-----BEGIN ' + pem_marker + b'-----',
+            b'-----END ' + pem_marker + b'-----')
 
 
 
 
 def load_pem(contents, pem_marker):
 def load_pem(contents, pem_marker):
@@ -81,7 +82,7 @@ def load_pem(contents, pem_marker):
             break
             break
 
 
         # Load fields
         # Load fields
-        if b(':') in line:
+        if b':' in line:
             continue
             continue
 
 
         pem_lines.append(line)
         pem_lines.append(line)
@@ -94,7 +95,7 @@ def load_pem(contents, pem_marker):
         raise ValueError('No PEM end marker "%s" found' % pem_end)
         raise ValueError('No PEM end marker "%s" found' % pem_end)
 
 
     # Base64-decode the contents
     # Base64-decode the contents
-    pem = b('').join(pem_lines)
+    pem = b''.join(pem_lines)
     return base64.standard_b64decode(pem)
     return base64.standard_b64decode(pem)
 
 
 
 
@@ -106,13 +107,13 @@ def save_pem(contents, pem_marker):
         when your file has '-----BEGIN RSA PRIVATE KEY-----' and
         when your file has '-----BEGIN RSA PRIVATE KEY-----' and
         '-----END RSA PRIVATE KEY-----' markers.
         '-----END RSA PRIVATE KEY-----' markers.
 
 
-    :return: the base64-encoded content between the start and end markers.
+    :return: the base64-encoded content between the start and end markers, as bytes.
 
 
     """
     """
 
 
     (pem_start, pem_end) = _markers(pem_marker)
     (pem_start, pem_end) = _markers(pem_marker)
 
 
-    b64 = base64.standard_b64encode(contents).replace(b('\n'), b(''))
+    b64 = base64.standard_b64encode(contents).replace(b'\n', b'')
     pem_lines = [pem_start]
     pem_lines = [pem_start]
 
 
     for block_start in range(0, len(b64), 64):
     for block_start in range(0, len(b64), 64):
@@ -120,6 +121,6 @@ def save_pem(contents, pem_marker):
         pem_lines.append(block)
         pem_lines.append(block)
 
 
     pem_lines.append(pem_end)
     pem_lines.append(pem_end)
-    pem_lines.append(b(''))
+    pem_lines.append(b'')
 
 
-    return b('\n').join(pem_lines)
+    return b'\n'.join(pem_lines)

+ 98 - 40
desktop/core/ext-py/rsa-3.4.2/rsa/pkcs1.py → desktop/core/ext-py/rsa-4.0/rsa/pkcs1.py

@@ -31,21 +31,23 @@ to your users.
 import hashlib
 import hashlib
 import os
 import os
 
 
-from rsa._compat import b
+from rsa._compat import range
 from rsa import common, transform, core
 from rsa import common, transform, core
 
 
 # ASN.1 codes that describe the hash algorithm used.
 # ASN.1 codes that describe the hash algorithm used.
 HASH_ASN1 = {
 HASH_ASN1 = {
-    'MD5': b('\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10'),
-    'SHA-1': b('\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14'),
-    'SHA-256': b('\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'),
-    'SHA-384': b('\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30'),
-    'SHA-512': b('\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40'),
+    'MD5': b'\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10',
+    'SHA-1': b'\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14',
+    'SHA-224': b'\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c',
+    'SHA-256': b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20',
+    'SHA-384': b'\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30',
+    'SHA-512': b'\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40',
 }
 }
 
 
 HASH_METHODS = {
 HASH_METHODS = {
     'MD5': hashlib.md5,
     'MD5': hashlib.md5,
     'SHA-1': hashlib.sha1,
     'SHA-1': hashlib.sha1,
+    'SHA-224': hashlib.sha224,
     'SHA-256': hashlib.sha256,
     'SHA-256': hashlib.sha256,
     'SHA-384': hashlib.sha384,
     'SHA-384': hashlib.sha384,
     'SHA-512': hashlib.sha512,
     'SHA-512': hashlib.sha512,
@@ -87,7 +89,7 @@ def _pad_for_encryption(message, target_length):
                             ' space for %i' % (msglength, max_msglength))
                             ' space for %i' % (msglength, max_msglength))
 
 
     # Get random padding
     # Get random padding
-    padding = b('')
+    padding = b''
     padding_length = target_length - msglength - 3
     padding_length = target_length - msglength - 3
 
 
     # We remove 0-bytes, so we'll end up with less padding than we've asked for,
     # We remove 0-bytes, so we'll end up with less padding than we've asked for,
@@ -99,15 +101,15 @@ def _pad_for_encryption(message, target_length):
         # after removing the 0-bytes. This increases the chance of getting
         # after removing the 0-bytes. This increases the chance of getting
         # enough bytes, especially when needed_bytes is small
         # enough bytes, especially when needed_bytes is small
         new_padding = os.urandom(needed_bytes + 5)
         new_padding = os.urandom(needed_bytes + 5)
-        new_padding = new_padding.replace(b('\x00'), b(''))
+        new_padding = new_padding.replace(b'\x00', b'')
         padding = padding + new_padding[:needed_bytes]
         padding = padding + new_padding[:needed_bytes]
 
 
     assert len(padding) == padding_length
     assert len(padding) == padding_length
 
 
-    return b('').join([b('\x00\x02'),
-                       padding,
-                       b('\x00'),
-                       message])
+    return b''.join([b'\x00\x02',
+                     padding,
+                     b'\x00',
+                     message])
 
 
 
 
 def _pad_for_signing(message, target_length):
 def _pad_for_signing(message, target_length):
@@ -138,10 +140,10 @@ def _pad_for_signing(message, target_length):
 
 
     padding_length = target_length - msglength - 3
     padding_length = target_length - msglength - 3
 
 
-    return b('').join([b('\x00\x01'),
-                       padding_length * b('\xff'),
-                       b('\x00'),
-                       message])
+    return b''.join([b'\x00\x01',
+                     padding_length * b'\xff',
+                     b'\x00',
+                     message])
 
 
 
 
 def encrypt(message, pub_key):
 def encrypt(message, pub_key):
@@ -233,30 +235,29 @@ def decrypt(crypto, priv_key):
     cleartext = transform.int2bytes(decrypted, blocksize)
     cleartext = transform.int2bytes(decrypted, blocksize)
 
 
     # If we can't find the cleartext marker, decryption failed.
     # If we can't find the cleartext marker, decryption failed.
-    if cleartext[0:2] != b('\x00\x02'):
+    if cleartext[0:2] != b'\x00\x02':
         raise DecryptionError('Decryption failed')
         raise DecryptionError('Decryption failed')
 
 
     # Find the 00 separator between the padding and the message
     # Find the 00 separator between the padding and the message
     try:
     try:
-        sep_idx = cleartext.index(b('\x00'), 2)
+        sep_idx = cleartext.index(b'\x00', 2)
     except ValueError:
     except ValueError:
         raise DecryptionError('Decryption failed')
         raise DecryptionError('Decryption failed')
 
 
     return cleartext[sep_idx + 1:]
     return cleartext[sep_idx + 1:]
 
 
 
 
-def sign(message, priv_key, hash):
-    """Signs the message with the private key.
+def sign_hash(hash_value, priv_key, hash_method):
+    """Signs a precomputed hash with the private key.
 
 
     Hashes the message, then signs the hash with the given key. This is known
     Hashes the message, then signs the hash with the given key. This is known
     as a "detached signature", because the message itself isn't altered.
     as a "detached signature", because the message itself isn't altered.
 
 
-    :param message: the message to sign. Can be an 8-bit string or a file-like
-        object. If ``message`` has a ``read()`` method, it is assumed to be a
-        file-like object.
+    :param hash_value: A precomputed hash to sign (ignores message). Should be set to
+        None if needing to hash and sign message.
     :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
     :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
-    :param hash: the hash method used on the message. Use 'MD5', 'SHA-1',
-        'SHA-256', 'SHA-384' or 'SHA-512'.
+    :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1',
+        'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'.
     :return: a message signature block.
     :return: a message signature block.
     :raise OverflowError: if the private key is too small to contain the
     :raise OverflowError: if the private key is too small to contain the
         requested hash.
         requested hash.
@@ -264,15 +265,12 @@ def sign(message, priv_key, hash):
     """
     """
 
 
     # Get the ASN1 code for this hash method
     # Get the ASN1 code for this hash method
-    if hash not in HASH_ASN1:
-        raise ValueError('Invalid hash method: %s' % hash)
-    asn1code = HASH_ASN1[hash]
-
-    # Calculate the hash
-    hash = _hash(message, hash)
+    if hash_method not in HASH_ASN1:
+        raise ValueError('Invalid hash method: %s' % hash_method)
+    asn1code = HASH_ASN1[hash_method]
 
 
     # Encrypt the hash with the private key
     # Encrypt the hash with the private key
-    cleartext = asn1code + hash
+    cleartext = asn1code + hash_value
     keylength = common.byte_size(priv_key.n)
     keylength = common.byte_size(priv_key.n)
     padded = _pad_for_signing(cleartext, keylength)
     padded = _pad_for_signing(cleartext, keylength)
 
 
@@ -283,6 +281,28 @@ def sign(message, priv_key, hash):
     return block
     return block
 
 
 
 
+def sign(message, priv_key, hash_method):
+    """Signs the message with the private key.
+
+    Hashes the message, then signs the hash with the given key. This is known
+    as a "detached signature", because the message itself isn't altered.
+
+    :param message: the message to sign. Can be an 8-bit string or a file-like
+        object. If ``message`` has a ``read()`` method, it is assumed to be a
+        file-like object.
+    :param priv_key: the :py:class:`rsa.PrivateKey` to sign with
+    :param hash_method: the hash method used on the message. Use 'MD5', 'SHA-1',
+        'SHA-224', SHA-256', 'SHA-384' or 'SHA-512'.
+    :return: a message signature block.
+    :raise OverflowError: if the private key is too small to contain the
+        requested hash.
+
+    """
+
+    msg_hash = compute_hash(message, hash_method)
+    return sign_hash(msg_hash, priv_key, hash_method)
+
+
 def verify(message, signature, pub_key):
 def verify(message, signature, pub_key):
     """Verifies that the signature matches the message.
     """Verifies that the signature matches the message.
 
 
@@ -294,6 +314,7 @@ def verify(message, signature, pub_key):
     :param signature: the signature block, as created with :py:func:`rsa.sign`.
     :param signature: the signature block, as created with :py:func:`rsa.sign`.
     :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message.
     :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message.
     :raise VerificationError: when the signature doesn't match the message.
     :raise VerificationError: when the signature doesn't match the message.
+    :returns: the name of the used hash.
 
 
     """
     """
 
 
@@ -304,7 +325,7 @@ def verify(message, signature, pub_key):
 
 
     # Get the hash method
     # Get the hash method
     method_name = _find_method_hash(clearsig)
     method_name = _find_method_hash(clearsig)
-    message_hash = _hash(message, method_name)
+    message_hash = compute_hash(message, method_name)
 
 
     # Reconstruct the expected padded hash
     # Reconstruct the expected padded hash
     cleartext = HASH_ASN1[method_name] + message_hash
     cleartext = HASH_ASN1[method_name] + message_hash
@@ -314,10 +335,50 @@ def verify(message, signature, pub_key):
     if expected != clearsig:
     if expected != clearsig:
         raise VerificationError('Verification failed')
         raise VerificationError('Verification failed')
 
 
-    return True
+    return method_name
+
 
 
+def find_signature_hash(signature, pub_key):
+    """Returns the hash name detected from the signature.
 
 
-def _hash(message, method_name):
+    If you also want to verify the message, use :py:func:`rsa.verify()` instead.
+    It also returns the name of the used hash.
+
+    :param signature: the signature block, as created with :py:func:`rsa.sign`.
+    :param pub_key: the :py:class:`rsa.PublicKey` of the person signing the message.
+    :returns: the name of the used hash.
+    """
+
+    keylength = common.byte_size(pub_key.n)
+    encrypted = transform.bytes2int(signature)
+    decrypted = core.decrypt_int(encrypted, pub_key.e, pub_key.n)
+    clearsig = transform.int2bytes(decrypted, keylength)
+
+    return _find_method_hash(clearsig)
+
+
+def yield_fixedblocks(infile, blocksize):
+    """Generator, yields each block of ``blocksize`` bytes in the input file.
+
+    :param infile: file to read and separate in blocks.
+    :param blocksize: block size in bytes.
+    :returns: a generator that yields the contents of each block
+    """
+
+    while True:
+        block = infile.read(blocksize)
+
+        read_bytes = len(block)
+        if read_bytes == 0:
+            break
+
+        yield block
+
+        if read_bytes < blocksize:
+            break
+
+
+def compute_hash(message, method_name):
     """Returns the message digest.
     """Returns the message digest.
 
 
     :param message: the signed message. Can be an 8-bit string or a file-like
     :param message: the signed message. Can be an 8-bit string or a file-like
@@ -335,11 +396,8 @@ def _hash(message, method_name):
     hasher = method()
     hasher = method()
 
 
     if hasattr(message, 'read') and hasattr(message.read, '__call__'):
     if hasattr(message, 'read') and hasattr(message.read, '__call__'):
-        # Late import to prevent DeprecationWarnings.
-        from . import varblock
-
         # read as 1K blocks
         # read as 1K blocks
-        for block in varblock.yield_fixedblocks(message, 1024):
+        for block in yield_fixedblocks(message, 1024):
             hasher.update(block)
             hasher.update(block)
     else:
     else:
         # hash the message object itself.
         # hash the message object itself.
@@ -375,7 +433,7 @@ if __name__ == '__main__':
         if failures:
         if failures:
             break
             break
 
 
-        if count and count % 100 == 0:
+        if count % 100 == 0 and count:
             print('%i times' % count)
             print('%i times' % count)
 
 
     print('Doctests done')
     print('Doctests done')

+ 103 - 0
desktop/core/ext-py/rsa-4.0/rsa/pkcs1_v2.py

@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+#
+#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+"""Functions for PKCS#1 version 2 encryption and signing
+
+This module implements certain functionality from PKCS#1 version 2. Main
+documentation is RFC 2437: https://tools.ietf.org/html/rfc2437
+"""
+
+from rsa._compat import range
+from rsa import (
+    common,
+    pkcs1,
+    transform,
+)
+
+
+def mgf1(seed, length, hasher='SHA-1'):
+    """
+    MGF1 is a Mask Generation Function based on a hash function.
+
+    A mask generation function takes an octet string of variable length and a
+    desired output length as input, and outputs an octet string of the desired
+    length. The plaintext-awareness of RSAES-OAEP relies on the random nature of
+    the output of the mask generation function, which in turn relies on the
+    random nature of the underlying hash.
+
+    :param bytes seed: seed from which mask is generated, an octet string
+    :param int length: intended length in octets of the mask, at most 2^32(hLen)
+    :param str hasher: hash function (hLen denotes the length in octets of the hash
+        function output)
+
+    :return: mask, an octet string of length `length`
+    :rtype: bytes
+
+    :raise OverflowError: when `length` is too large for the specified `hasher`
+    :raise ValueError: when specified `hasher` is invalid
+    """
+
+    try:
+        hash_length = pkcs1.HASH_METHODS[hasher]().digest_size
+    except KeyError:
+        raise ValueError(
+            'Invalid `hasher` specified. Please select one of: {hash_list}'.format(
+                hash_list=', '.join(sorted(pkcs1.HASH_METHODS.keys()))
+            )
+        )
+
+    # If l > 2^32(hLen), output "mask too long" and stop.
+    if length > (2**32 * hash_length):
+        raise OverflowError(
+            "Desired length should be at most 2**32 times the hasher's output "
+            "length ({hash_length} for {hasher} function)".format(
+                hash_length=hash_length,
+                hasher=hasher,
+            )
+        )
+
+    # Looping `counter` from 0 to ceil(l / hLen)-1, build `output` based on the
+    # hashes formed by (`seed` + C), being `C` an octet string of length 4
+    # generated by converting `counter` with the primitive I2OSP
+    output = b''.join(
+        pkcs1.compute_hash(
+            seed + transform.int2bytes(counter, fill_size=4),
+            method_name=hasher,
+        )
+        for counter in range(common.ceil_div(length, hash_length) + 1)
+    )
+
+    # Output the leading `length` octets of `output` as the octet string mask.
+    return output[:length]
+
+
+__all__ = [
+    'mgf1',
+]
+
+if __name__ == '__main__':
+    print('Running doctests 1000x or until failure')
+    import doctest
+
+    for count in range(1000):
+        (failures, tests) = doctest.testmod()
+        if failures:
+            break
+
+        if count % 100 == 0 and count:
+            print('%i times' % count)
+
+    print('Doctests done')

+ 36 - 13
desktop/core/ext-py/rsa-3.4.2/rsa/prime.py → desktop/core/ext-py/rsa-4.0/rsa/prime.py

@@ -20,6 +20,8 @@ Implementation based on the book Algorithm Design by Michael T. Goodrich and
 Roberto Tamassia, 2002.
 Roberto Tamassia, 2002.
 """
 """
 
 
+from rsa._compat import range
+import rsa.common
 import rsa.randnum
 import rsa.randnum
 
 
 __all__ = ['getprime', 'are_relatively_prime']
 __all__ = ['getprime', 'are_relatively_prime']
@@ -37,6 +39,32 @@ def gcd(p, q):
     return p
     return p
 
 
 
 
+def get_primality_testing_rounds(number):
+    """Returns minimum number of rounds for Miller-Rabing primality testing,
+    based on number bitsize.
+
+    According to NIST FIPS 186-4, Appendix C, Table C.3, minimum number of
+    rounds of M-R testing, using an error probability of 2 ** (-100), for
+    different p, q bitsizes are:
+      * p, q bitsize: 512; rounds: 7
+      * p, q bitsize: 1024; rounds: 4
+      * p, q bitsize: 1536; rounds: 3
+    See: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+    """
+
+    # Calculate number bitsize.
+    bitsize = rsa.common.bit_size(number)
+    # Set number of rounds.
+    if bitsize >= 1536:
+        return 3
+    if bitsize >= 1024:
+        return 4
+    if bitsize >= 512:
+        return 7
+    # For smaller bitsizes, set arbitrary number of rounds.
+    return 10
+
+
 def miller_rabin_primality_testing(n, k):
 def miller_rabin_primality_testing(n, k):
     """Calculates whether n is composite (which is always correct) or prime
     """Calculates whether n is composite (which is always correct) or prime
     (which theoretically is incorrect with error probability 4**-k), by
     (which theoretically is incorrect with error probability 4**-k), by
@@ -69,7 +97,7 @@ def miller_rabin_primality_testing(n, k):
     # Test k witnesses.
     # Test k witnesses.
     for _ in range(k):
     for _ in range(k):
         # Generate random integer a, where 2 <= a <= (n - 2)
         # Generate random integer a, where 2 <= a <= (n - 2)
-        a = rsa.randnum.randint(n - 4) + 2
+        a = rsa.randnum.randint(n - 3) + 1
 
 
         x = pow(a, d, n)
         x = pow(a, d, n)
         if x == 1 or x == n - 1:
         if x == 1 or x == n - 1:
@@ -99,26 +127,21 @@ def is_prime(number):
     False
     False
     >>> is_prime(41)
     >>> is_prime(41)
     True
     True
-    >>> [x for x in range(901, 1000) if is_prime(x)]
-    [907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
     """
     """
 
 
     # Check for small numbers.
     # Check for small numbers.
     if number < 10:
     if number < 10:
-        return number in [2, 3, 5, 7]
+        return number in {2, 3, 5, 7}
 
 
     # Check for even numbers.
     # Check for even numbers.
     if not (number & 1):
     if not (number & 1):
         return False
         return False
 
 
-    # According to NIST FIPS 186-4, Appendix C, Table C.3, minimum number of
-    # rounds of M-R testing, using an error probability of 2 ** (-100), for
-    # different p, q bitsizes are:
-    #   * p, q bitsize: 512; rounds: 7
-    #   * p, q bitsize: 1024; rounds: 4
-    #   * p, q bitsize: 1536; rounds: 3
-    # See: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
-    return miller_rabin_primality_testing(number, 7)
+    # Calculate minimum number of rounds.
+    k = get_primality_testing_rounds(number)
+
+    # Run primality testing with (minimum + 1) rounds.
+    return miller_rabin_primality_testing(number, k + 1)
 
 
 
 
 def getprime(nbits):
 def getprime(nbits):
@@ -172,7 +195,7 @@ if __name__ == '__main__':
         if failures:
         if failures:
             break
             break
 
 
-        if count and count % 100 == 0:
+        if count % 100 == 0 and count:
             print('%i times' % count)
             print('%i times' % count)
 
 
     print('Doctests done')
     print('Doctests done')

+ 1 - 1
desktop/core/ext-py/rsa-3.4.2/rsa/randnum.py → desktop/core/ext-py/rsa-4.0/rsa/randnum.py

@@ -88,7 +88,7 @@ def randint(maxvalue):
         if value <= maxvalue:
         if value <= maxvalue:
             break
             break
 
 
-        if tries and tries % 10 == 0:
+        if tries % 10 == 0 and tries:
             # After a lot of tries to get the right number of bits but still
             # After a lot of tries to get the right number of bits but still
             # smaller than maxvalue, decrease the number of bits by 1. That'll
             # smaller than maxvalue, decrease the number of bits by 1. That'll
             # dramatically increase the chances to get a large enough number.
             # dramatically increase the chances to get a large enough number.

+ 14 - 23
desktop/core/ext-py/rsa-3.4.2/rsa/transform.py → desktop/core/ext-py/rsa-4.0/rsa/transform.py

@@ -21,20 +21,11 @@ From bytes to a number, number to bytes, etc.
 
 
 from __future__ import absolute_import
 from __future__ import absolute_import
 
 
-try:
-    # We'll use psyco if available on 32-bit architectures to speed up code.
-    # Using psyco (if available) cuts down the execution time on Python 2.5
-    # at least by half.
-    import psyco
-
-    psyco.full()
-except ImportError:
-    pass
-
 import binascii
 import binascii
 from struct import pack
 from struct import pack
-from rsa import common
-from rsa._compat import is_integer, b, byte, get_word_alignment, ZERO_BYTE, EMPTY_BYTE
+
+from rsa._compat import byte, is_integer
+from rsa import common, machine_size
 
 
 
 
 def bytes2int(raw_bytes):
 def bytes2int(raw_bytes):
@@ -92,7 +83,7 @@ def _int2bytes(number, block_size=None):
     # Do some bounds checking
     # Do some bounds checking
     if number == 0:
     if number == 0:
         needed_bytes = 1
         needed_bytes = 1
-        raw_bytes = [ZERO_BYTE]
+        raw_bytes = [b'\x00']
     else:
     else:
         needed_bytes = common.byte_size(number)
         needed_bytes = common.byte_size(number)
         raw_bytes = []
         raw_bytes = []
@@ -110,14 +101,14 @@ def _int2bytes(number, block_size=None):
 
 
     # Pad with zeroes to fill the block
     # Pad with zeroes to fill the block
     if block_size and block_size > 0:
     if block_size and block_size > 0:
-        padding = (block_size - needed_bytes) * ZERO_BYTE
+        padding = (block_size - needed_bytes) * b'\x00'
     else:
     else:
-        padding = EMPTY_BYTE
+        padding = b''
 
 
-    return padding + EMPTY_BYTE.join(raw_bytes)
+    return padding + b''.join(raw_bytes)
 
 
 
 
-def bytes_leading(raw_bytes, needle=ZERO_BYTE):
+def bytes_leading(raw_bytes, needle=b'\x00'):
     """
     """
     Finds the number of prefixed byte occurrences in the haystack.
     Finds the number of prefixed byte occurrences in the haystack.
 
 
@@ -126,7 +117,7 @@ def bytes_leading(raw_bytes, needle=ZERO_BYTE):
     :param raw_bytes:
     :param raw_bytes:
         Raw bytes.
         Raw bytes.
     :param needle:
     :param needle:
-        The byte to count. Default \000.
+        The byte to count. Default \x00.
     :returns:
     :returns:
         The number of leading needle bytes.
         The number of leading needle bytes.
     """
     """
@@ -186,11 +177,11 @@ def int2bytes(number, fill_size=None, chunk_size=None, overflow=False):
     # Ensure these are integers.
     # Ensure these are integers.
     number & 1
     number & 1
 
 
-    raw_bytes = b('')
+    raw_bytes = b''
 
 
     # Pack the integer one machine word at a time into bytes.
     # Pack the integer one machine word at a time into bytes.
     num = number
     num = number
-    word_bits, _, max_uint, pack_type = get_word_alignment(num)
+    word_bits, _, max_uint, pack_type = machine_size.get_word_alignment(num)
     pack_format = ">%s" % pack_type
     pack_format = ">%s" % pack_type
     while num > 0:
     while num > 0:
         raw_bytes = pack(pack_format, num & max_uint) + raw_bytes
         raw_bytes = pack(pack_format, num & max_uint) + raw_bytes
@@ -198,7 +189,7 @@ def int2bytes(number, fill_size=None, chunk_size=None, overflow=False):
     # Obtain the index of the first non-zero byte.
     # Obtain the index of the first non-zero byte.
     zero_leading = bytes_leading(raw_bytes)
     zero_leading = bytes_leading(raw_bytes)
     if number == 0:
     if number == 0:
-        raw_bytes = ZERO_BYTE
+        raw_bytes = b'\x00'
     # De-padding.
     # De-padding.
     raw_bytes = raw_bytes[zero_leading:]
     raw_bytes = raw_bytes[zero_leading:]
 
 
@@ -209,12 +200,12 @@ def int2bytes(number, fill_size=None, chunk_size=None, overflow=False):
                     "Need %d bytes for number, but fill size is %d" %
                     "Need %d bytes for number, but fill size is %d" %
                     (length, fill_size)
                     (length, fill_size)
             )
             )
-        raw_bytes = raw_bytes.rjust(fill_size, ZERO_BYTE)
+        raw_bytes = raw_bytes.rjust(fill_size, b'\x00')
     elif chunk_size and chunk_size > 0:
     elif chunk_size and chunk_size > 0:
         remainder = length % chunk_size
         remainder = length % chunk_size
         if remainder:
         if remainder:
             padding_size = chunk_size - remainder
             padding_size = chunk_size - remainder
-            raw_bytes = raw_bytes.rjust(length + padding_size, ZERO_BYTE)
+            raw_bytes = raw_bytes.rjust(length + padding_size, b'\x00')
     return raw_bytes
     return raw_bytes
 
 
 
 

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/rsa/util.py → desktop/core/ext-py/rsa-4.0/rsa/util.py


+ 10 - 11
desktop/core/ext-py/rsa-3.4.2/setup.cfg → desktop/core/ext-py/rsa-4.0/setup.cfg

@@ -1,11 +1,10 @@
-[nosetests]
-verbosity = 2
-
-[bdist_wheel]
-universal = 1
-
-[egg_info]
-tag_date = 0
-tag_svn_revision = 0
-tag_build = 
-
+[bdist_wheel]
+universal = 1
+
+[metadata]
+license_file = LICENSE
+
+[egg_info]
+tag_build = 
+tag_date = 0
+

+ 10 - 5
desktop/core/ext-py/rsa-3.4.2/setup.py → desktop/core/ext-py/rsa-4.0/setup.py

@@ -16,10 +16,15 @@
 
 
 from setuptools import setup
 from setuptools import setup
 
 
+with open('README.md') as f:
+    long_description = f.read()
+
 if __name__ == '__main__':
 if __name__ == '__main__':
     setup(name='rsa',
     setup(name='rsa',
-          version='3.4.2',
+          version='4.0',
           description='Pure-Python RSA implementation',
           description='Pure-Python RSA implementation',
+          long_description=long_description,
+          long_description_content_type='text/markdown',
           author='Sybren A. Stuvel',
           author='Sybren A. Stuvel',
           author_email='sybren@stuvel.eu',
           author_email='sybren@stuvel.eu',
           maintainer='Sybren A. Stuvel',
           maintainer='Sybren A. Stuvel',
@@ -36,12 +41,14 @@ if __name__ == '__main__':
               'Operating System :: OS Independent',
               'Operating System :: OS Independent',
               'Programming Language :: Python',
               'Programming Language :: Python',
               'Programming Language :: Python :: 2',
               'Programming Language :: Python :: 2',
-              'Programming Language :: Python :: 2.6',
               'Programming Language :: Python :: 2.7',
               'Programming Language :: Python :: 2.7',
               'Programming Language :: Python :: 3',
               'Programming Language :: Python :: 3',
-              'Programming Language :: Python :: 3.3',
               'Programming Language :: Python :: 3.4',
               'Programming Language :: Python :: 3.4',
               'Programming Language :: Python :: 3.5',
               'Programming Language :: Python :: 3.5',
+              'Programming Language :: Python :: 3.6',
+              'Programming Language :: Python :: 3.7',
+              'Programming Language :: Python :: Implementation :: CPython',
+              'Programming Language :: Python :: Implementation :: PyPy',
               'Topic :: Security :: Cryptography',
               'Topic :: Security :: Cryptography',
           ],
           ],
           install_requires=[
           install_requires=[
@@ -54,8 +61,6 @@ if __name__ == '__main__':
               'pyrsa-decrypt = rsa.cli:decrypt',
               'pyrsa-decrypt = rsa.cli:decrypt',
               'pyrsa-sign = rsa.cli:sign',
               'pyrsa-sign = rsa.cli:sign',
               'pyrsa-verify = rsa.cli:verify',
               'pyrsa-verify = rsa.cli:verify',
-              'pyrsa-encrypt-bigfile = rsa.cli:encrypt_bigfile',
-              'pyrsa-decrypt-bigfile = rsa.cli:decrypt_bigfile',
           ]},
           ]},
 
 
           )
           )

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/tests/__init__.py → desktop/core/ext-py/rsa-4.0/tests/__init__.py


+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/tests/private.pem → desktop/core/ext-py/rsa-4.0/tests/private.pem


+ 296 - 0
desktop/core/ext-py/rsa-4.0/tests/test_cli.py

@@ -0,0 +1,296 @@
+"""
+Unit tests for CLI entry points.
+"""
+
+from __future__ import print_function
+
+import unittest
+import sys
+import functools
+from contextlib import contextmanager
+
+import os
+from io import StringIO, BytesIO
+
+import rsa
+import rsa.cli
+import rsa.util
+from rsa._compat import PY2
+
+
+def make_buffer():
+    if PY2:
+        return BytesIO()
+    buf = StringIO()
+    buf.buffer = BytesIO()
+    return buf
+
+
+def get_bytes_out(out):
+    if PY2:
+        # Python 2.x writes 'str' to stdout
+        return out.getvalue()
+    # Python 3.x writes 'bytes' to stdout.buffer
+    return out.buffer.getvalue()
+
+
+@contextmanager
+def captured_output():
+    """Captures output to stdout and stderr"""
+
+    new_out, new_err = make_buffer(), make_buffer()
+    old_out, old_err = sys.stdout, sys.stderr
+    try:
+        sys.stdout, sys.stderr = new_out, new_err
+        yield new_out, new_err
+    finally:
+        sys.stdout, sys.stderr = old_out, old_err
+
+
+@contextmanager
+def cli_args(*new_argv):
+    """Updates sys.argv[1:] for a single test."""
+
+    old_args = sys.argv[:]
+    sys.argv[1:] = [str(arg) for arg in new_argv]
+
+    try:
+        yield
+    finally:
+        sys.argv[1:] = old_args
+
+
+def remove_if_exists(fname):
+    """Removes a file if it exists."""
+
+    if os.path.exists(fname):
+        os.unlink(fname)
+
+
+def cleanup_files(*filenames):
+    """Makes sure the files don't exist when the test runs, and deletes them afterward."""
+
+    def remove():
+        for fname in filenames:
+            remove_if_exists(fname)
+
+    def decorator(func):
+        @functools.wraps(func)
+        def wrapper(*args, **kwargs):
+            remove()
+            try:
+                return func(*args, **kwargs)
+            finally:
+                remove()
+
+        return wrapper
+
+    return decorator
+
+
+class AbstractCliTest(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        # Ensure there is a key to use
+        cls.pub_key, cls.priv_key = rsa.newkeys(512)
+        cls.pub_fname = '%s.pub' % cls.__name__
+        cls.priv_fname = '%s.key' % cls.__name__
+
+        with open(cls.pub_fname, 'wb') as outfile:
+            outfile.write(cls.pub_key.save_pkcs1())
+
+        with open(cls.priv_fname, 'wb') as outfile:
+            outfile.write(cls.priv_key.save_pkcs1())
+
+    @classmethod
+    def tearDownClass(cls):
+        if hasattr(cls, 'pub_fname'):
+            remove_if_exists(cls.pub_fname)
+        if hasattr(cls, 'priv_fname'):
+            remove_if_exists(cls.priv_fname)
+
+    def assertExits(self, status_code, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except SystemExit as ex:
+            if status_code == ex.code:
+                return
+            self.fail('SystemExit() raised by %r, but exited with code %r, expected %r' % (
+                func, ex.code, status_code))
+        else:
+            self.fail('SystemExit() not raised by %r' % func)
+
+
+class KeygenTest(AbstractCliTest):
+    def test_keygen_no_args(self):
+        with cli_args():
+            self.assertExits(1, rsa.cli.keygen)
+
+    def test_keygen_priv_stdout(self):
+        with captured_output() as (out, err):
+            with cli_args(128):
+                rsa.cli.keygen()
+
+        lines = get_bytes_out(out).splitlines()
+        self.assertEqual(b'-----BEGIN RSA PRIVATE KEY-----', lines[0])
+        self.assertEqual(b'-----END RSA PRIVATE KEY-----', lines[-1])
+
+        # The key size should be shown on stderr
+        self.assertTrue('128-bit key' in err.getvalue())
+
+    @cleanup_files('test_cli_privkey_out.pem')
+    def test_keygen_priv_out_pem(self):
+        with captured_output() as (out, err):
+            with cli_args('--out=test_cli_privkey_out.pem', '--form=PEM', 128):
+                rsa.cli.keygen()
+
+        # The key size should be shown on stderr
+        self.assertTrue('128-bit key' in err.getvalue())
+
+        # The output file should be shown on stderr
+        self.assertTrue('test_cli_privkey_out.pem' in err.getvalue())
+
+        # If we can load the file as PEM, it's good enough.
+        with open('test_cli_privkey_out.pem', 'rb') as pemfile:
+            rsa.PrivateKey.load_pkcs1(pemfile.read())
+
+    @cleanup_files('test_cli_privkey_out.der')
+    def test_keygen_priv_out_der(self):
+        with captured_output() as (out, err):
+            with cli_args('--out=test_cli_privkey_out.der', '--form=DER', 128):
+                rsa.cli.keygen()
+
+        # The key size should be shown on stderr
+        self.assertTrue('128-bit key' in err.getvalue())
+
+        # The output file should be shown on stderr
+        self.assertTrue('test_cli_privkey_out.der' in err.getvalue())
+
+        # If we can load the file as der, it's good enough.
+        with open('test_cli_privkey_out.der', 'rb') as derfile:
+            rsa.PrivateKey.load_pkcs1(derfile.read(), format='DER')
+
+    @cleanup_files('test_cli_privkey_out.pem', 'test_cli_pubkey_out.pem')
+    def test_keygen_pub_out_pem(self):
+        with captured_output() as (out, err):
+            with cli_args('--out=test_cli_privkey_out.pem',
+                          '--pubout=test_cli_pubkey_out.pem',
+                          '--form=PEM', 256):
+                rsa.cli.keygen()
+
+        # The key size should be shown on stderr
+        self.assertTrue('256-bit key' in err.getvalue())
+
+        # The output files should be shown on stderr
+        self.assertTrue('test_cli_privkey_out.pem' in err.getvalue())
+        self.assertTrue('test_cli_pubkey_out.pem' in err.getvalue())
+
+        # If we can load the file as PEM, it's good enough.
+        with open('test_cli_pubkey_out.pem', 'rb') as pemfile:
+            rsa.PublicKey.load_pkcs1(pemfile.read())
+
+
+class EncryptDecryptTest(AbstractCliTest):
+    def test_empty_decrypt(self):
+        with cli_args():
+            self.assertExits(1, rsa.cli.decrypt)
+
+    def test_empty_encrypt(self):
+        with cli_args():
+            self.assertExits(1, rsa.cli.encrypt)
+
+    @cleanup_files('encrypted.txt', 'cleartext.txt')
+    def test_encrypt_decrypt(self):
+        with open('cleartext.txt', 'wb') as outfile:
+            outfile.write(b'Hello cleartext RSA users!')
+
+        with cli_args('-i', 'cleartext.txt', '--out=encrypted.txt', self.pub_fname):
+            with captured_output():
+                rsa.cli.encrypt()
+
+        with cli_args('-i', 'encrypted.txt', self.priv_fname):
+            with captured_output() as (out, err):
+                rsa.cli.decrypt()
+
+        # We should have the original cleartext on stdout now.
+        output = get_bytes_out(out)
+        self.assertEqual(b'Hello cleartext RSA users!', output)
+
+    @cleanup_files('encrypted.txt', 'cleartext.txt')
+    def test_encrypt_decrypt_unhappy(self):
+        with open('cleartext.txt', 'wb') as outfile:
+            outfile.write(b'Hello cleartext RSA users!')
+
+        with cli_args('-i', 'cleartext.txt', '--out=encrypted.txt', self.pub_fname):
+            with captured_output():
+                rsa.cli.encrypt()
+
+        # Change a few bytes in the encrypted stream.
+        with open('encrypted.txt', 'r+b') as encfile:
+            encfile.seek(40)
+            encfile.write(b'hahaha')
+
+        with cli_args('-i', 'encrypted.txt', self.priv_fname):
+            with captured_output() as (out, err):
+                self.assertRaises(rsa.DecryptionError, rsa.cli.decrypt)
+
+
+class SignVerifyTest(AbstractCliTest):
+    def test_empty_verify(self):
+        with cli_args():
+            self.assertExits(1, rsa.cli.verify)
+
+    def test_empty_sign(self):
+        with cli_args():
+            self.assertExits(1, rsa.cli.sign)
+
+    @cleanup_files('signature.txt', 'cleartext.txt')
+    def test_sign_verify(self):
+        with open('cleartext.txt', 'wb') as outfile:
+            outfile.write(b'Hello RSA users!')
+
+        with cli_args('-i', 'cleartext.txt', '--out=signature.txt', self.priv_fname, 'SHA-256'):
+            with captured_output():
+                rsa.cli.sign()
+
+        with cli_args('-i', 'cleartext.txt', self.pub_fname, 'signature.txt'):
+            with captured_output() as (out, err):
+                rsa.cli.verify()
+
+        self.assertFalse(b'Verification OK' in get_bytes_out(out))
+
+    @cleanup_files('signature.txt', 'cleartext.txt')
+    def test_sign_verify_unhappy(self):
+        with open('cleartext.txt', 'wb') as outfile:
+            outfile.write(b'Hello RSA users!')
+
+        with cli_args('-i', 'cleartext.txt', '--out=signature.txt', self.priv_fname, 'SHA-256'):
+            with captured_output():
+                rsa.cli.sign()
+
+        # Change a few bytes in the cleartext file.
+        with open('cleartext.txt', 'r+b') as encfile:
+            encfile.seek(6)
+            encfile.write(b'DSA')
+
+        with cli_args('-i', 'cleartext.txt', self.pub_fname, 'signature.txt'):
+            with captured_output() as (out, err):
+                self.assertExits('Verification failed.', rsa.cli.verify)
+
+
+class PrivatePublicTest(AbstractCliTest):
+    """Test CLI command to convert a private to a public key."""
+
+    @cleanup_files('test_private_to_public.pem')
+    def test_private_to_public(self):
+
+        with cli_args('-i', self.priv_fname, '-o', 'test_private_to_public.pem'):
+            with captured_output():
+                rsa.util.private_to_public()
+
+        # Check that the key is indeed valid.
+        with open('test_private_to_public.pem', 'rb') as pemfile:
+            key = rsa.PublicKey.load_pkcs1(pemfile.read())
+
+        self.assertEqual(self.priv_key.n, key.n)
+        self.assertEqual(self.priv_key.e, key.e)

+ 29 - 10
desktop/core/ext-py/rsa-3.4.2/tests/test_common.py → desktop/core/ext-py/rsa-4.0/tests/test_common.py

@@ -17,14 +17,14 @@
 
 
 import unittest
 import unittest
 import struct
 import struct
-from rsa._compat import byte, b
-from rsa.common import byte_size, bit_size, _bit_size
+from rsa._compat import byte
+from rsa.common import byte_size, bit_size, inverse
 
 
 
 
 class TestByte(unittest.TestCase):
 class TestByte(unittest.TestCase):
     def test_values(self):
     def test_values(self):
-        self.assertEqual(byte(0), b('\x00'))
-        self.assertEqual(byte(255), b('\xff'))
+        self.assertEqual(byte(0), b'\x00')
+        self.assertEqual(byte(255), b'\xff')
 
 
     def test_struct_error_when_out_of_bounds(self):
     def test_struct_error_when_out_of_bounds(self):
         self.assertRaises(struct.error, byte, 256)
         self.assertRaises(struct.error, byte, 256)
@@ -69,9 +69,28 @@ class TestBitSize(unittest.TestCase):
         self.assertEqual(bit_size((1 << 1024) + 1), 1025)
         self.assertEqual(bit_size((1 << 1024) + 1), 1025)
         self.assertEqual(bit_size((1 << 1024) - 1), 1024)
         self.assertEqual(bit_size((1 << 1024) - 1), 1024)
 
 
-        self.assertEqual(_bit_size(1023), 10)
-        self.assertEqual(_bit_size(1024), 11)
-        self.assertEqual(_bit_size(1025), 11)
-        self.assertEqual(_bit_size(1 << 1024), 1025)
-        self.assertEqual(_bit_size((1 << 1024) + 1), 1025)
-        self.assertEqual(_bit_size((1 << 1024) - 1), 1024)
+    def test_negative_values(self):
+        self.assertEqual(bit_size(-1023), 10)
+        self.assertEqual(bit_size(-1024), 11)
+        self.assertEqual(bit_size(-1025), 11)
+        self.assertEqual(bit_size(-1 << 1024), 1025)
+        self.assertEqual(bit_size(-((1 << 1024) + 1)), 1025)
+        self.assertEqual(bit_size(-((1 << 1024) - 1)), 1024)
+
+    def test_bad_type(self):
+        self.assertRaises(TypeError, bit_size, [])
+        self.assertRaises(TypeError, bit_size, ())
+        self.assertRaises(TypeError, bit_size, dict())
+        self.assertRaises(TypeError, bit_size, "")
+        self.assertRaises(TypeError, bit_size, None)
+        self.assertRaises(TypeError, bit_size, 0.0)
+
+
+class TestInverse(unittest.TestCase):
+    def test_normal(self):
+        self.assertEqual(3, inverse(7, 4))
+        self.assertEqual(9, inverse(5, 11))
+
+    def test_not_relprime(self):
+        self.assertRaises(ValueError, inverse, 4, 8)
+        self.assertRaises(ValueError, inverse, 25, 5)

+ 80 - 0
desktop/core/ext-py/rsa-4.0/tests/test_compat.py

@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+#
+#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import unittest
+import struct
+
+from rsa._compat import byte, is_bytes, range, xor_bytes
+
+
+class TestByte(unittest.TestCase):
+    """Tests for single bytes."""
+
+    def test_byte(self):
+        for i in range(256):
+            byt = byte(i)
+            self.assertTrue(is_bytes(byt))
+            self.assertEqual(ord(byt), i)
+
+    def test_raises_StructError_on_overflow(self):
+        self.assertRaises(struct.error, byte, 256)
+        self.assertRaises(struct.error, byte, -1)
+
+    def test_byte_literal(self):
+        self.assertIsInstance(b'abc', bytes)
+
+
+class TestBytes(unittest.TestCase):
+    """Tests for bytes objects."""
+
+    def setUp(self):
+        self.b1 = b'\xff\xff\xff\xff'
+        self.b2 = b'\x00\x00\x00\x00'
+        self.b3 = b'\xf0\xf0\xf0\xf0'
+        self.b4 = b'\x4d\x23\xca\xe2'
+        self.b5 = b'\x9b\x61\x3b\xdc'
+        self.b6 = b'\xff\xff'
+
+        self.byte_strings = (self.b1, self.b2, self.b3, self.b4, self.b5, self.b6)
+
+    def test_xor_bytes(self):
+        self.assertEqual(xor_bytes(self.b1, self.b2), b'\xff\xff\xff\xff')
+        self.assertEqual(xor_bytes(self.b1, self.b3), b'\x0f\x0f\x0f\x0f')
+        self.assertEqual(xor_bytes(self.b1, self.b4), b'\xb2\xdc\x35\x1d')
+        self.assertEqual(xor_bytes(self.b1, self.b5), b'\x64\x9e\xc4\x23')
+        self.assertEqual(xor_bytes(self.b2, self.b3), b'\xf0\xf0\xf0\xf0')
+        self.assertEqual(xor_bytes(self.b2, self.b4), b'\x4d\x23\xca\xe2')
+        self.assertEqual(xor_bytes(self.b2, self.b5), b'\x9b\x61\x3b\xdc')
+        self.assertEqual(xor_bytes(self.b3, self.b4), b'\xbd\xd3\x3a\x12')
+        self.assertEqual(xor_bytes(self.b3, self.b5), b'\x6b\x91\xcb\x2c')
+        self.assertEqual(xor_bytes(self.b4, self.b5), b'\xd6\x42\xf1\x3e')
+
+    def test_xor_bytes_length(self):
+        self.assertEqual(xor_bytes(self.b1, self.b6), b'\x00\x00')
+        self.assertEqual(xor_bytes(self.b2, self.b6), b'\xff\xff')
+        self.assertEqual(xor_bytes(self.b3, self.b6), b'\x0f\x0f')
+        self.assertEqual(xor_bytes(self.b4, self.b6), b'\xb2\xdc')
+        self.assertEqual(xor_bytes(self.b5, self.b6), b'\x64\x9e')
+        self.assertEqual(xor_bytes(self.b6, b''), b'')
+
+    def test_xor_bytes_commutative(self):
+        for first in self.byte_strings:
+            for second in self.byte_strings:
+                min_length = min(len(first), len(second))
+                result = xor_bytes(first, second)
+
+                self.assertEqual(result, xor_bytes(second, first))
+                self.assertEqual(len(result), min_length)

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/tests/test_integers.py → desktop/core/ext-py/rsa-4.0/tests/test_integers.py


+ 79 - 0
desktop/core/ext-py/rsa-4.0/tests/test_key.py

@@ -0,0 +1,79 @@
+"""
+Some tests for the rsa/key.py file.
+"""
+
+import unittest
+
+import rsa.key
+import rsa.core
+
+
+class BlindingTest(unittest.TestCase):
+    def test_blinding(self):
+        """Test blinding and unblinding.
+
+        This is basically the doctest of the PrivateKey.blind method, but then
+        implemented as unittest to allow running on different Python versions.
+        """
+
+        pk = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
+
+        message = 12345
+        encrypted = rsa.core.encrypt_int(message, pk.e, pk.n)
+
+        blinded = pk.blind(encrypted, 4134431)  # blind before decrypting
+        decrypted = rsa.core.decrypt_int(blinded, pk.d, pk.n)
+        unblinded = pk.unblind(decrypted, 4134431)
+
+        self.assertEqual(unblinded, message)
+
+
+class KeyGenTest(unittest.TestCase):
+    def test_custom_exponent(self):
+        priv, pub = rsa.key.newkeys(16, exponent=3)
+
+        self.assertEqual(3, priv.e)
+        self.assertEqual(3, pub.e)
+
+    def test_default_exponent(self):
+        priv, pub = rsa.key.newkeys(16)
+
+        self.assertEqual(0x10001, priv.e)
+        self.assertEqual(0x10001, pub.e)
+
+    def test_exponents_coefficient_calculation(self):
+        pk = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
+
+        self.assertEqual(pk.exp1, 55063)
+        self.assertEqual(pk.exp2, 10095)
+        self.assertEqual(pk.coef, 50797)
+
+    def test_custom_getprime_func(self):
+        # List of primes to test with, in order [p, q, p, q, ....]
+        # By starting with two of the same primes, we test that this is
+        # properly rejected.
+        primes = [64123, 64123, 64123, 50957, 39317, 33107]
+
+        def getprime(_):
+            return primes.pop(0)
+
+        # This exponent will cause two other primes to be generated.
+        exponent = 136407
+
+        (p, q, e, d) = rsa.key.gen_keys(64,
+                                        accurate=False,
+                                        getprime_func=getprime,
+                                        exponent=exponent)
+        self.assertEqual(39317, p)
+        self.assertEqual(33107, q)
+
+
+class HashTest(unittest.TestCase):
+    """Test hashing of keys"""
+
+    def test_hash_possible(self):
+        priv, pub = rsa.key.newkeys(16)
+
+        # This raises a TypeError when hashing isn't possible.
+        hash(priv)
+        hash(pub)

+ 59 - 18
desktop/core/ext-py/rsa-3.4.2/tests/test_load_save_keys.py → desktop/core/ext-py/rsa-4.0/tests/test_load_save_keys.py

@@ -14,62 +14,63 @@
 #  See the License for the specific language governing permissions and
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 #  limitations under the License.
 
 
-'''Unittest for saving and loading keys.'''
+"""Unittest for saving and loading keys."""
 
 
 import base64
 import base64
-import unittest
+import mock
 import os.path
 import os.path
 import pickle
 import pickle
+import unittest
+import warnings
 
 
-from rsa._compat import b
-
+from rsa._compat import range
 import rsa.key
 import rsa.key
 
 
-B64PRIV_DER = b('MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt')
+B64PRIV_DER = b'MC4CAQACBQDeKYlRAgMBAAECBQDHn4npAgMA/icCAwDfxwIDANcXAgInbwIDAMZt'
 PRIVATE_DER = base64.standard_b64decode(B64PRIV_DER)
 PRIVATE_DER = base64.standard_b64decode(B64PRIV_DER)
 
 
-B64PUB_DER = b('MAwCBQDeKYlRAgMBAAE=')
+B64PUB_DER = b'MAwCBQDeKYlRAgMBAAE='
 PUBLIC_DER = base64.standard_b64decode(B64PUB_DER)
 PUBLIC_DER = base64.standard_b64decode(B64PUB_DER)
 
 
-PRIVATE_PEM = b('''
+PRIVATE_PEM = b'''\
 -----BEGIN CONFUSING STUFF-----
 -----BEGIN CONFUSING STUFF-----
 Cruft before the key
 Cruft before the key
 
 
 -----BEGIN RSA PRIVATE KEY-----
 -----BEGIN RSA PRIVATE KEY-----
 Comment: something blah
 Comment: something blah
 
 
-%s
+''' + B64PRIV_DER + b'''
 -----END RSA PRIVATE KEY-----
 -----END RSA PRIVATE KEY-----
 
 
 Stuff after the key
 Stuff after the key
 -----END CONFUSING STUFF-----
 -----END CONFUSING STUFF-----
-''' % B64PRIV_DER.decode("utf-8"))
+'''
 
 
-CLEAN_PRIVATE_PEM = b('''\
+CLEAN_PRIVATE_PEM = b'''\
 -----BEGIN RSA PRIVATE KEY-----
 -----BEGIN RSA PRIVATE KEY-----
-%s
+''' + B64PRIV_DER + b'''
 -----END RSA PRIVATE KEY-----
 -----END RSA PRIVATE KEY-----
-''' % B64PRIV_DER.decode("utf-8"))
+'''
 
 
-PUBLIC_PEM = b('''
+PUBLIC_PEM = b'''\
 -----BEGIN CONFUSING STUFF-----
 -----BEGIN CONFUSING STUFF-----
 Cruft before the key
 Cruft before the key
 
 
 -----BEGIN RSA PUBLIC KEY-----
 -----BEGIN RSA PUBLIC KEY-----
 Comment: something blah
 Comment: something blah
 
 
-%s
+''' + B64PUB_DER + b'''
 -----END RSA PUBLIC KEY-----
 -----END RSA PUBLIC KEY-----
 
 
 Stuff after the key
 Stuff after the key
 -----END CONFUSING STUFF-----
 -----END CONFUSING STUFF-----
-''' % B64PUB_DER.decode("utf-8"))
+'''
 
 
-CLEAN_PUBLIC_PEM = b('''\
+CLEAN_PUBLIC_PEM = b'''\
 -----BEGIN RSA PUBLIC KEY-----
 -----BEGIN RSA PUBLIC KEY-----
-%s
+''' + B64PUB_DER + b'''
 -----END RSA PUBLIC KEY-----
 -----END RSA PUBLIC KEY-----
-''' % B64PUB_DER.decode("utf-8"))
+'''
 
 
 
 
 class DerTest(unittest.TestCase):
 class DerTest(unittest.TestCase):
@@ -82,6 +83,39 @@ class DerTest(unittest.TestCase):
         expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
 
 
         self.assertEqual(expected, key)
         self.assertEqual(expected, key)
+        self.assertEqual(key.exp1, 55063)
+        self.assertEqual(key.exp2, 10095)
+        self.assertEqual(key.coef, 50797)
+
+    @mock.patch('pyasn1.codec.der.decoder.decode')
+    def test_load_malformed_private_key(self, der_decode):
+        """Test loading malformed private DER keys."""
+
+        # Decode returns an invalid exp2 value.
+        der_decode.return_value = (
+            [0, 3727264081, 65537, 3349121513, 65063, 57287, 55063, 0, 50797],
+            0,
+        )
+
+        with warnings.catch_warnings(record=True) as w:
+            # Always print warnings
+            warnings.simplefilter('always')
+
+            # Load 3 keys
+            for _ in range(3):
+                key = rsa.key.PrivateKey.load_pkcs1(PRIVATE_DER, 'DER')
+
+            # Check that 3 warnings were generated.
+            self.assertEqual(3, len(w))
+
+            for warning in w:
+                self.assertTrue(issubclass(warning.category, UserWarning))
+                self.assertIn('malformed', str(warning.message))
+
+        # Check that we are creating the key with correct values
+        self.assertEqual(key.exp1, 55063)
+        self.assertEqual(key.exp2, 10095)
+        self.assertEqual(key.coef, 50797)
 
 
     def test_save_private_key(self):
     def test_save_private_key(self):
         """Test saving private DER keys."""
         """Test saving private DER keys."""
@@ -89,6 +123,7 @@ class DerTest(unittest.TestCase):
         key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         der = key.save_pkcs1('DER')
         der = key.save_pkcs1('DER')
 
 
+        self.assertIsInstance(der, bytes)
         self.assertEqual(PRIVATE_DER, der)
         self.assertEqual(PRIVATE_DER, der)
 
 
     def test_load_public_key(self):
     def test_load_public_key(self):
@@ -105,6 +140,7 @@ class DerTest(unittest.TestCase):
         key = rsa.key.PublicKey(3727264081, 65537)
         key = rsa.key.PublicKey(3727264081, 65537)
         der = key.save_pkcs1('DER')
         der = key.save_pkcs1('DER')
 
 
+        self.assertIsInstance(der, bytes)
         self.assertEqual(PUBLIC_DER, der)
         self.assertEqual(PUBLIC_DER, der)
 
 
 
 
@@ -118,6 +154,9 @@ class PemTest(unittest.TestCase):
         expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         expected = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
 
 
         self.assertEqual(expected, key)
         self.assertEqual(expected, key)
+        self.assertEqual(key.exp1, 55063)
+        self.assertEqual(key.exp2, 10095)
+        self.assertEqual(key.coef, 50797)
 
 
     def test_save_private_key(self):
     def test_save_private_key(self):
         """Test saving private PEM files."""
         """Test saving private PEM files."""
@@ -125,6 +164,7 @@ class PemTest(unittest.TestCase):
         key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         key = rsa.key.PrivateKey(3727264081, 65537, 3349121513, 65063, 57287)
         pem = key.save_pkcs1('PEM')
         pem = key.save_pkcs1('PEM')
 
 
+        self.assertIsInstance(pem, bytes)
         self.assertEqual(CLEAN_PRIVATE_PEM, pem)
         self.assertEqual(CLEAN_PRIVATE_PEM, pem)
 
 
     def test_load_public_key(self):
     def test_load_public_key(self):
@@ -141,6 +181,7 @@ class PemTest(unittest.TestCase):
         key = rsa.key.PublicKey(3727264081, 65537)
         key = rsa.key.PublicKey(3727264081, 65537)
         pem = key.save_pkcs1('PEM')
         pem = key.save_pkcs1('PEM')
 
 
+        self.assertIsInstance(pem, bytes)
         self.assertEqual(CLEAN_PUBLIC_PEM, pem)
         self.assertEqual(CLEAN_PUBLIC_PEM, pem)
 
 
     def test_load_from_disk(self):
     def test_load_from_disk(self):

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/tests/test_parallel.py → desktop/core/ext-py/rsa-4.0/tests/test_parallel.py


+ 31 - 3
desktop/core/ext-py/rsa-3.4.2/tests/test_pem.py → desktop/core/ext-py/rsa-4.0/tests/test_pem.py

@@ -17,7 +17,7 @@
 
 
 import unittest
 import unittest
 
 
-from rsa._compat import b
+from rsa._compat import is_bytes
 from rsa.pem import _markers
 from rsa.pem import _markers
 import rsa.key
 import rsa.key
 
 
@@ -49,8 +49,8 @@ prime2 = 88103681619592083641803383393198542599284510949756076218404908654323473
 class TestMarkers(unittest.TestCase):
 class TestMarkers(unittest.TestCase):
     def test_values(self):
     def test_values(self):
         self.assertEqual(_markers('RSA PRIVATE KEY'),
         self.assertEqual(_markers('RSA PRIVATE KEY'),
-                         (b('-----BEGIN RSA PRIVATE KEY-----'),
-                          b('-----END RSA PRIVATE KEY-----')))
+                         (b'-----BEGIN RSA PRIVATE KEY-----',
+                          b'-----END RSA PRIVATE KEY-----'))
 
 
 
 
 class TestBytesAndStrings(unittest.TestCase):
 class TestBytesAndStrings(unittest.TestCase):
@@ -72,3 +72,31 @@ class TestBytesAndStrings(unittest.TestCase):
         key = rsa.key.PrivateKey.load_pkcs1(private_key_pem.encode('ascii'))
         key = rsa.key.PrivateKey.load_pkcs1(private_key_pem.encode('ascii'))
         self.assertEqual(prime1, key.p)
         self.assertEqual(prime1, key.p)
         self.assertEqual(prime2, key.q)
         self.assertEqual(prime2, key.q)
+
+
+class TestByteOutput(unittest.TestCase):
+    """Tests that PEM and DER are returned as bytes."""
+
+    def test_bytes_public(self):
+        key = rsa.key.PublicKey.load_pkcs1_openssl_pem(public_key_pem)
+        self.assertTrue(is_bytes(key.save_pkcs1(format='DER')))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='PEM')))
+
+    def test_bytes_private(self):
+        key = rsa.key.PrivateKey.load_pkcs1(private_key_pem)
+        self.assertTrue(is_bytes(key.save_pkcs1(format='DER')))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='PEM')))
+
+
+class TestByteInput(unittest.TestCase):
+    """Tests that PEM and DER can be loaded from bytes."""
+
+    def test_bytes_public(self):
+        key = rsa.key.PublicKey.load_pkcs1_openssl_pem(public_key_pem.encode('ascii'))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='DER')))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='PEM')))
+
+    def test_bytes_private(self):
+        key = rsa.key.PrivateKey.load_pkcs1(private_key_pem.encode('ascii'))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='DER')))
+        self.assertTrue(is_bytes(key.save_pkcs1(format='PEM')))

+ 36 - 9
desktop/core/ext-py/rsa-3.4.2/tests/test_pkcs1.py → desktop/core/ext-py/rsa-4.0/tests/test_pkcs1.py

@@ -21,7 +21,7 @@ import unittest
 
 
 import rsa
 import rsa
 from rsa import pkcs1
 from rsa import pkcs1
-from rsa._compat import byte, b, is_bytes
+from rsa._compat import byte, is_bytes
 
 
 
 
 class BinaryTest(unittest.TestCase):
 class BinaryTest(unittest.TestCase):
@@ -48,7 +48,8 @@ class BinaryTest(unittest.TestCase):
         a = encrypted[5]
         a = encrypted[5]
         if is_bytes(a):
         if is_bytes(a):
             a = ord(a)
             a = ord(a)
-        encrypted = encrypted[:5] + byte(a + 1) + encrypted[6:]
+        altered_a = (a + 1) % 256
+        encrypted = encrypted[:5] + byte(altered_a) + encrypted[6:]
 
 
         self.assertRaises(pkcs1.DecryptionError, pkcs1.decrypt, encrypted,
         self.assertRaises(pkcs1.DecryptionError, pkcs1.decrypt, encrypted,
                           self.priv)
                           self.priv)
@@ -72,27 +73,32 @@ class SignatureTest(unittest.TestCase):
     def test_sign_verify(self):
     def test_sign_verify(self):
         """Test happy flow of sign and verify"""
         """Test happy flow of sign and verify"""
 
 
-        message = b('je moeder')
-        print("\tMessage:   %r" % message)
+        message = b'je moeder'
+        signature = pkcs1.sign(message, self.priv, 'SHA-256')
+
+        self.assertEqual('SHA-256', pkcs1.verify(message, signature, self.pub))
+
+    def test_find_signature_hash(self):
+        """Test happy flow of sign and find_signature_hash"""
 
 
+        message = b'je moeder'
         signature = pkcs1.sign(message, self.priv, 'SHA-256')
         signature = pkcs1.sign(message, self.priv, 'SHA-256')
-        print("\tSignature: %r" % signature)
 
 
-        self.assertTrue(pkcs1.verify(message, signature, self.pub))
+        self.assertEqual('SHA-256', pkcs1.find_signature_hash(signature, self.pub))
 
 
     def test_alter_message(self):
     def test_alter_message(self):
         """Altering the message should let the verification fail."""
         """Altering the message should let the verification fail."""
 
 
-        signature = pkcs1.sign(b('je moeder'), self.priv, 'SHA-256')
+        signature = pkcs1.sign(b'je moeder', self.priv, 'SHA-256')
         self.assertRaises(pkcs1.VerificationError, pkcs1.verify,
         self.assertRaises(pkcs1.VerificationError, pkcs1.verify,
-                          b('mijn moeder'), signature, self.pub)
+                          b'mijn moeder', signature, self.pub)
 
 
     def test_sign_different_key(self):
     def test_sign_different_key(self):
         """Signing with another key should let the verification fail."""
         """Signing with another key should let the verification fail."""
 
 
         (otherpub, _) = rsa.newkeys(512)
         (otherpub, _) = rsa.newkeys(512)
 
 
-        message = b('je moeder')
+        message = b'je moeder'
         signature = pkcs1.sign(message, self.priv, 'SHA-256')
         signature = pkcs1.sign(message, self.priv, 'SHA-256')
         self.assertRaises(pkcs1.VerificationError, pkcs1.verify,
         self.assertRaises(pkcs1.VerificationError, pkcs1.verify,
                           message, signature, otherpub)
                           message, signature, otherpub)
@@ -105,3 +111,24 @@ class SignatureTest(unittest.TestCase):
         signature2 = pkcs1.sign(message, self.priv, 'SHA-1')
         signature2 = pkcs1.sign(message, self.priv, 'SHA-1')
 
 
         self.assertEqual(signature1, signature2)
         self.assertEqual(signature1, signature2)
+
+    def test_split_hash_sign(self):
+        """Hashing and then signing should match with directly signing the message. """
+
+        message = b'je moeder'
+        msg_hash = pkcs1.compute_hash(message, 'SHA-256')
+        signature1 = pkcs1.sign_hash(msg_hash, self.priv, 'SHA-256')
+
+        # Calculate the signature using the unified method
+        signature2 = pkcs1.sign(message, self.priv, 'SHA-256')
+
+        self.assertEqual(signature1, signature2)
+
+    def test_hash_sign_verify(self):
+        """Test happy flow of hash, sign, and verify"""
+
+        message = b'je moeder'
+        msg_hash = pkcs1.compute_hash(message, 'SHA-224')
+        signature = pkcs1.sign_hash(msg_hash, self.priv, 'SHA-224')
+
+        self.assertTrue(pkcs1.verify(message, signature, self.pub))

+ 83 - 0
desktop/core/ext-py/rsa-4.0/tests/test_pkcs1_v2.py

@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+#
+#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+"""Tests PKCS #1 version 2 functionality.
+
+Most of the mocked values come from the test vectors found at:
+http://www.itomorrowmag.com/emc-plus/rsa-labs/standards-initiatives/pkcs-rsa-cryptography-standard.htm
+"""
+
+import unittest
+
+from rsa import pkcs1_v2
+
+
+class MGFTest(unittest.TestCase):
+    def test_oaep_int_db_mask(self):
+        seed = (
+            b'\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2'
+            b'\xf0\x6c\xb5\x8f'
+        )
+        db = (
+            b'\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90'
+            b'\xaf\xd8\x07\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xd4\x36\xe9\x95\x69'
+            b'\xfd\x32\xa7\xc8\xa0\x5b\xbc\x90\xd3\x2c\x49'
+        )
+        masked_db = (
+            b'\xdc\xd8\x7d\x5c\x68\xf1\xee\xa8\xf5\x52\x67\xc3\x1b\x2e\x8b\xb4'
+            b'\x25\x1f\x84\xd7\xe0\xb2\xc0\x46\x26\xf5\xaf\xf9\x3e\xdc\xfb\x25'
+            b'\xc9\xc2\xb3\xff\x8a\xe1\x0e\x83\x9a\x2d\xdb\x4c\xdc\xfe\x4f\xf4'
+            b'\x77\x28\xb4\xa1\xb7\xc1\x36\x2b\xaa\xd2\x9a\xb4\x8d\x28\x69\xd5'
+            b'\x02\x41\x21\x43\x58\x11\x59\x1b\xe3\x92\xf9\x82\xfb\x3e\x87\xd0'
+            b'\x95\xae\xb4\x04\x48\xdb\x97\x2f\x3a\xc1\x4f\x7b\xc2\x75\x19\x52'
+            b'\x81\xce\x32\xd2\xf1\xb7\x6d\x4d\x35\x3e\x2d'
+        )
+
+        # dbMask = MGF(seed, length(DB))
+        db_mask = pkcs1_v2.mgf1(seed, length=len(db))
+        expected_db_mask = (
+            b'\x06\xe1\xde\xb2\x36\x9a\xa5\xa5\xc7\x07\xd8\x2c\x8e\x4e\x93\x24'
+            b'\x8a\xc7\x83\xde\xe0\xb2\xc0\x46\x26\xf5\xaf\xf9\x3e\xdc\xfb\x25'
+            b'\xc9\xc2\xb3\xff\x8a\xe1\x0e\x83\x9a\x2d\xdb\x4c\xdc\xfe\x4f\xf4'
+            b'\x77\x28\xb4\xa1\xb7\xc1\x36\x2b\xaa\xd2\x9a\xb4\x8d\x28\x69\xd5'
+            b'\x02\x41\x21\x43\x58\x11\x59\x1b\xe3\x92\xf9\x82\xfb\x3e\x87\xd0'
+            b'\x95\xae\xb4\x04\x48\xdb\x97\x2f\x3a\xc1\x4e\xaf\xf4\x9c\x8c\x3b'
+            b'\x7c\xfc\x95\x1a\x51\xec\xd1\xdd\xe6\x12\x64'
+        )
+
+        self.assertEqual(db_mask, expected_db_mask)
+
+        # seedMask = MGF(maskedDB, length(seed))
+        seed_mask = pkcs1_v2.mgf1(masked_db, length=len(seed))
+        expected_seed_mask = (
+            b'\x41\x87\x0b\x5a\xb0\x29\xe6\x57\xd9\x57\x50\xb5\x4c\x28\x3c\x08'
+            b'\x72\x5d\xbe\xa9'
+        )
+
+        self.assertEqual(seed_mask, expected_seed_mask)
+
+    def test_invalid_hasher(self):
+        """Tests an invalid hasher generates an exception"""
+        with self.assertRaises(ValueError):
+            pkcs1_v2.mgf1(b'\x06\xe1\xde\xb2', length=8, hasher='SHA2')
+
+    def test_invalid_length(self):
+        with self.assertRaises(OverflowError):
+            pkcs1_v2.mgf1(b'\x06\xe1\xde\xb2', length=2**50)

+ 110 - 0
desktop/core/ext-py/rsa-4.0/tests/test_prime.py

@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+#
+#  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+"""Tests prime functions."""
+
+import unittest
+
+from rsa._compat import range
+import rsa.prime
+import rsa.randnum
+
+
+class PrimeTest(unittest.TestCase):
+    def test_is_prime(self):
+        """Test some common primes."""
+
+        # Test some trivial numbers
+        self.assertFalse(rsa.prime.is_prime(-1))
+        self.assertFalse(rsa.prime.is_prime(0))
+        self.assertFalse(rsa.prime.is_prime(1))
+        self.assertTrue(rsa.prime.is_prime(2))
+        self.assertFalse(rsa.prime.is_prime(42))
+        self.assertTrue(rsa.prime.is_prime(41))
+
+        # Test some slightly larger numbers
+        self.assertEqual(
+            [907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997],
+            [x for x in range(901, 1000) if rsa.prime.is_prime(x)]
+        )
+
+        # Test around the 50th millionth known prime.
+        self.assertTrue(rsa.prime.is_prime(982451653))
+        self.assertFalse(rsa.prime.is_prime(982451653 * 961748941))
+
+    def test_miller_rabin_primality_testing(self):
+        """Uses monkeypatching to ensure certain random numbers.
+
+        This allows us to predict/control the code path.
+        """
+
+        randints = []
+
+        def fake_randint(maxvalue):
+            return randints.pop(0)
+
+        orig_randint = rsa.randnum.randint
+        rsa.randnum.randint = fake_randint
+        try:
+            # 'n is composite'
+            randints.append(2630484832)  # causes the 'n is composite' case with n=3784949785
+            self.assertEqual(False, rsa.prime.miller_rabin_primality_testing(2787998641, 7))
+            self.assertEqual([], randints)
+
+            # 'Exit inner loop and continue with next witness'
+            randints.extend([
+                2119139098,  # causes 'Exit inner loop and continue with next witness'
+                # the next witnesses for the above case:
+                3051067716, 3603501763, 3230895847, 3687808133, 3760099987, 4026931495, 3022471882,
+            ])
+            self.assertEqual(True, rsa.prime.miller_rabin_primality_testing(2211417913,
+                                                                            len(randints)))
+            self.assertEqual([], randints)
+        finally:
+            rsa.randnum.randint = orig_randint
+
+    def test_mersenne_primes(self):
+        """Tests first known Mersenne primes.
+
+        Mersenne primes are prime numbers that can be written in the form
+        `Mn = 2**n - 1` for some integer `n`. For the list of known Mersenne
+        primes, see:
+        https://en.wikipedia.org/wiki/Mersenne_prime#List_of_known_Mersenne_primes
+        """
+
+        # List of known Mersenne exponents.
+        known_mersenne_exponents = [
+            2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279,
+            2203, 2281, 4423,
+        ]
+
+        # Test Mersenne primes.
+        for exp in known_mersenne_exponents:
+            self.assertTrue(rsa.prime.is_prime(2**exp - 1))
+
+    def test_get_primality_testing_rounds(self):
+        """Test round calculation for primality testing."""
+
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 63),  10)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 127), 10)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 255), 10)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 511),  7)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 767),  7)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1023), 4)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1279), 4)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 1535), 3)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 2047), 3)
+        self.assertEqual(rsa.prime.get_primality_testing_rounds(1 << 4095), 3)

+ 0 - 0
desktop/core/ext-py/rsa-3.4.2/tests/test_strings.py → desktop/core/ext-py/rsa-4.0/tests/test_strings.py


+ 12 - 13
desktop/core/ext-py/rsa-3.4.2/tests/test_transform.py → desktop/core/ext-py/rsa-4.0/tests/test_transform.py

@@ -15,37 +15,36 @@
 #  limitations under the License.
 #  limitations under the License.
 
 
 import unittest
 import unittest
-from rsa._compat import b
 from rsa.transform import int2bytes, bytes2int, _int2bytes
 from rsa.transform import int2bytes, bytes2int, _int2bytes
 
 
 
 
 class Test_int2bytes(unittest.TestCase):
 class Test_int2bytes(unittest.TestCase):
     def test_accuracy(self):
     def test_accuracy(self):
-        self.assertEqual(int2bytes(123456789), b('\x07[\xcd\x15'))
-        self.assertEqual(_int2bytes(123456789), b('\x07[\xcd\x15'))
+        self.assertEqual(int2bytes(123456789), b'\x07[\xcd\x15')
+        self.assertEqual(_int2bytes(123456789), b'\x07[\xcd\x15')
 
 
     def test_codec_identity(self):
     def test_codec_identity(self):
         self.assertEqual(bytes2int(int2bytes(123456789, 128)), 123456789)
         self.assertEqual(bytes2int(int2bytes(123456789, 128)), 123456789)
         self.assertEqual(bytes2int(_int2bytes(123456789, 128)), 123456789)
         self.assertEqual(bytes2int(_int2bytes(123456789, 128)), 123456789)
 
 
     def test_chunk_size(self):
     def test_chunk_size(self):
-        self.assertEqual(int2bytes(123456789, 6), b('\x00\x00\x07[\xcd\x15'))
+        self.assertEqual(int2bytes(123456789, 6), b'\x00\x00\x07[\xcd\x15')
         self.assertEqual(int2bytes(123456789, 7),
         self.assertEqual(int2bytes(123456789, 7),
-                         b('\x00\x00\x00\x07[\xcd\x15'))
+                         b'\x00\x00\x00\x07[\xcd\x15')
 
 
         self.assertEqual(_int2bytes(123456789, 6),
         self.assertEqual(_int2bytes(123456789, 6),
-                         b('\x00\x00\x07[\xcd\x15'))
+                         b'\x00\x00\x07[\xcd\x15')
         self.assertEqual(_int2bytes(123456789, 7),
         self.assertEqual(_int2bytes(123456789, 7),
-                         b('\x00\x00\x00\x07[\xcd\x15'))
+                         b'\x00\x00\x00\x07[\xcd\x15')
 
 
     def test_zero(self):
     def test_zero(self):
-        self.assertEqual(int2bytes(0, 4), b('\x00') * 4)
-        self.assertEqual(int2bytes(0, 7), b('\x00') * 7)
-        self.assertEqual(int2bytes(0), b('\x00'))
+        self.assertEqual(int2bytes(0, 4), b'\x00' * 4)
+        self.assertEqual(int2bytes(0, 7), b'\x00' * 7)
+        self.assertEqual(int2bytes(0), b'\x00')
 
 
-        self.assertEqual(_int2bytes(0, 4), b('\x00') * 4)
-        self.assertEqual(_int2bytes(0, 7), b('\x00') * 7)
-        self.assertEqual(_int2bytes(0), b('\x00'))
+        self.assertEqual(_int2bytes(0, 4), b'\x00' * 4)
+        self.assertEqual(_int2bytes(0, 7), b'\x00' * 7)
+        self.assertEqual(_int2bytes(0), b'\x00')
 
 
     def test_correctness_against_base_implementation(self):
     def test_correctness_against_base_implementation(self):
         # Slow test.
         # Slow test.