aboutsummaryrefslogtreecommitdiff
path: root/frozen_deps/Crypto/PublicKey/pubkey.py
blob: e46b07602fa5936e61369af983692443ccda5fef (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#
#   pubkey.py : Internal functions for public key operations
#
#  Part of the Python Cryptography Toolkit
#
#  Written by Andrew Kuchling, Paul Swartz, and others
#
# ===================================================================
# The contents of this file are dedicated to the public domain.  To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
#

__revision__ = "$Id$"

import types, warnings
from Crypto.Util.number import *

# Basic public key class
class pubkey:
    """An abstract class for a public key object.

    :undocumented: __getstate__, __setstate__, __eq__, __ne__, validate
    """
    def __init__(self):
        pass

    def __getstate__(self):
        """To keep key objects platform-independent, the key data is
        converted to standard Python long integers before being
        written out.  It will then be reconverted as necessary on
        restoration."""
        d=self.__dict__
        for key in self.keydata:
            if key in d: d[key]=int(d[key])
        return d

    def __setstate__(self, d):
        """On unpickling a key object, the key data is converted to the big
number representation being used, whether that is Python long
integers, MPZ objects, or whatever."""
        for key in self.keydata:
            if key in d: self.__dict__[key]=bignum(d[key])

    def encrypt(self, plaintext, K):
        """Encrypt a piece of data.

        :Parameter plaintext: The piece of data to encrypt.
        :Type plaintext: byte string or long

        :Parameter K: A random parameter required by some algorithms
        :Type K: byte string or long

        :Return: A tuple with two items. Each item is of the same type as the
         plaintext (string or long).
        """
        wasString=0
        if isinstance(plaintext, bytes):
            plaintext=bytes_to_long(plaintext) ; wasString=1
        if isinstance(K, bytes):
            K=bytes_to_long(K)
        ciphertext=self._encrypt(plaintext, K)
        if wasString: return tuple(map(long_to_bytes, ciphertext))
        else: return ciphertext

    def decrypt(self, ciphertext):
        """Decrypt a piece of data. 

        :Parameter ciphertext: The piece of data to decrypt.
        :Type ciphertext: byte string, long or a 2-item tuple as returned by `encrypt`

        :Return: A byte string if ciphertext was a byte string or a tuple
         of byte strings. A long otherwise.
        """
        wasString=0
        if not isinstance(ciphertext, tuple):
            ciphertext=(ciphertext,)
        if isinstance(ciphertext[0], bytes):
            ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1
        plaintext=self._decrypt(ciphertext)
        if wasString: return long_to_bytes(plaintext)
        else: return plaintext

    def sign(self, M, K):
        """Sign a piece of data.

        :Parameter M: The piece of data to encrypt.
        :Type M: byte string or long

        :Parameter K: A random parameter required by some algorithms
        :Type K: byte string or long

        :Return: A tuple with two items.
        """
        if (not self.has_private()):
            raise TypeError('Private key not available in this object')
        if isinstance(M, bytes): M=bytes_to_long(M)
        if isinstance(K, bytes): K=bytes_to_long(K)
        return self._sign(M, K)

    def verify (self, M, signature):
        """Verify the validity of a signature.

        :Parameter M: The expected message.
        :Type M: byte string or long

        :Parameter signature: The signature to verify.
        :Type signature: tuple with two items, as return by `sign`

        :Return: True if the signature is correct, False otherwise.
        """
        if isinstance(M, bytes): M=bytes_to_long(M)
        return self._verify(M, signature)

    # alias to compensate for the old validate() name
    def validate (self, M, signature):
        warnings.warn("validate() method name is obsolete; use verify()",
                      DeprecationWarning)

    def blind(self, M, B):
        """Blind a message to prevent certain side-channel attacks.
       
        :Parameter M: The message to blind.
        :Type M: byte string or long

        :Parameter B: Blinding factor.
        :Type B: byte string or long

        :Return: A byte string if M was so. A long otherwise.
        """
        wasString=0
        if isinstance(M, bytes):
            M=bytes_to_long(M) ; wasString=1
        if isinstance(B, bytes): B=bytes_to_long(B)
        blindedmessage=self._blind(M, B)
        if wasString: return long_to_bytes(blindedmessage)
        else: return blindedmessage

    def unblind(self, M, B):
        """Unblind a message after cryptographic processing.
        
        :Parameter M: The encoded message to unblind.
        :Type M: byte string or long

        :Parameter B: Blinding factor.
        :Type B: byte string or long
        """
        wasString=0
        if isinstance(M, bytes):
            M=bytes_to_long(M) ; wasString=1
        if isinstance(B, bytes): B=bytes_to_long(B)
        unblindedmessage=self._unblind(M, B)
        if wasString: return long_to_bytes(unblindedmessage)
        else: return unblindedmessage


    # The following methods will usually be left alone, except for
    # signature-only algorithms.  They both return Boolean values
    # recording whether this key's algorithm can sign and encrypt.
    def can_sign (self):
        """Tell if the algorithm can deal with cryptographic signatures.

        This property concerns the *algorithm*, not the key itself.
        It may happen that this particular key object hasn't got
        the private information required to generate a signature.

        :Return: boolean
        """
        return 1

    def can_encrypt (self):
        """Tell if the algorithm can deal with data encryption.
       
        This property concerns the *algorithm*, not the key itself.
        It may happen that this particular key object hasn't got
        the private information required to decrypt data.

        :Return: boolean
        """
        return 1

    def can_blind (self):
        """Tell if the algorithm can deal with data blinding.
       
        This property concerns the *algorithm*, not the key itself.
        It may happen that this particular key object hasn't got
        the private information required carry out blinding.

        :Return: boolean
        """
        return 0

    # The following methods will certainly be overridden by
    # subclasses.

    def size (self):
        """Tell the maximum number of bits that can be handled by this key.

        :Return: int
        """
        return 0

    def has_private (self):
        """Tell if the key object contains private components.

        :Return: bool
        """
        return 0

    def publickey (self):
        """Construct a new key carrying only the public information.

        :Return: A new `pubkey` object.
        """
        return self

    def __eq__ (self, other):
        """__eq__(other): 0, 1
        Compare us to other for equality.
        """
        return self.__getstate__() == other.__getstate__()

    def __ne__ (self, other):
        """__ne__(other): 0, 1
        Compare us to other for inequality.
        """
        return not self.__eq__(other)