/ adafruit_rsa / core.py
core.py
 1  # -*- coding: utf-8 -*-
 2  #
 3  #  Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
 4  #
 5  #  Licensed under the Apache License, Version 2.0 (the "License");
 6  #  you may not use this file except in compliance with the License.
 7  #  You may obtain a copy of the License at
 8  #
 9  #      https://www.apache.org/licenses/LICENSE-2.0
10  #
11  #  Unless required by applicable law or agreed to in writing, software
12  #  distributed under the License is distributed on an "AS IS" BASIS,
13  #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  #  See the License for the specific language governing permissions and
15  #  limitations under the License.
16  
17  """Core mathematical operations.
18  
19  This is the actual core RSA implementation, which is only defined
20  mathematically on integers.
21  """
22  
23  # pylint: disable=invalid-name
24  from adafruit_rsa._compat import is_integer
25  
26  __version__ = "0.0.0-auto.0"
27  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RSA.git"
28  
29  
30  def fast_pow(x, e, m):
31      """Performs fast modular exponentiation, saves RAM on small CPUs/micros.
32      :param int x: Base
33      :param int y: Exponent
34      :param int e: Second exponent
35      """
36      X = x
37      E = e
38      Y = 1
39      while E > 0:
40          if E % 2 == 0:
41              X = (X * X) % m
42              E = E // 2
43          else:
44              Y = (X * Y) % m
45              E = E - 1
46      return Y
47  
48  
49  def assert_int(var, name):
50      """Asserts provided variable is an integer."""
51      if is_integer(var):
52          return
53  
54      raise TypeError("%s should be an integer, not %s" % (name, var.__class__))
55  
56  
57  def encrypt_int(message, ekey, n):
58      """Encrypts a message using encryption key 'ekey', working modulo n"""
59  
60      assert_int(message, "message")
61      assert_int(ekey, "ekey")
62      assert_int(n, "n")
63  
64      if message < 0:
65          raise ValueError("Only non-negative numbers are supported")
66  
67      if message > n:
68          raise OverflowError("The message %i is too long for n=%i" % (message, n))
69  
70      # return pow(message, ekey, n)
71      # print('fast_pow({},{},{})'.format(message,ekey,n))
72      return fast_pow(message, ekey, n)
73  
74  
75  def decrypt_int(cyphertext, dkey, n):
76      """Decrypts a cypher text using the decryption key 'dkey', working modulo n"""
77  
78      assert_int(cyphertext, "cyphertext")
79      assert_int(dkey, "dkey")
80      assert_int(n, "n")
81  
82      message = fast_pow(cyphertext, dkey, n)
83      return message