- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / utils / RSAKey.py
1 """Abstract class for RSA."""
2
3 from cryptomath import *
4
5
6 class RSAKey:
7     """This is an abstract base class for RSA keys.
8
9     Particular implementations of RSA keys, such as
10     L{OpenSSL_RSAKey.OpenSSL_RSAKey},
11     L{Python_RSAKey.Python_RSAKey}, and
12     L{PyCrypto_RSAKey.PyCrypto_RSAKey},
13     inherit from this.
14
15     To create or parse an RSA key, don't use one of these classes
16     directly.  Instead, use the factory functions in
17     L{tlslite.utils.keyfactory}.
18     """
19
20     def __init__(self, n=0, e=0):
21         """Create a new RSA key.
22
23         If n and e are passed in, the new key will be initialized.
24
25         @type n: int
26         @param n: RSA modulus.
27
28         @type e: int
29         @param e: RSA public exponent.
30         """
31         raise NotImplementedError()
32
33     def __len__(self):
34         """Return the length of this key in bits.
35
36         @rtype: int
37         """
38         return numBits(self.n)
39
40     def hasPrivateKey(self):
41         """Return whether or not this key has a private component.
42
43         @rtype: bool
44         """
45         raise NotImplementedError()
46
47     def hash(self):
48         """Return the cryptoID <keyHash> value corresponding to this
49         key.
50
51         @rtype: str
52         """
53         raise NotImplementedError()
54
55     def getSigningAlgorithm(self):
56         """Return the cryptoID sigAlgo value corresponding to this key.
57
58         @rtype: str
59         """
60         return "pkcs1-sha1"
61
62     def hashAndSign(self, bytes):
63         """Hash and sign the passed-in bytes.
64
65         This requires the key to have a private component.  It performs
66         a PKCS1-SHA1 signature on the passed-in data.
67
68         @type bytes: str or L{array.array} of unsigned bytes
69         @param bytes: The value which will be hashed and signed.
70
71         @rtype: L{array.array} of unsigned bytes.
72         @return: A PKCS1-SHA1 signature on the passed-in data.
73         """
74         if not isinstance(bytes, type("")):
75             bytes = bytesToString(bytes)
76         hashBytes = stringToBytes(sha.sha(bytes).digest())
77         prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes)
78         sigBytes = self.sign(prefixedHashBytes)
79         return sigBytes
80
81     def hashAndVerify(self, sigBytes, bytes):
82         """Hash and verify the passed-in bytes with the signature.
83
84         This verifies a PKCS1-SHA1 signature on the passed-in data.
85
86         @type sigBytes: L{array.array} of unsigned bytes
87         @param sigBytes: A PKCS1-SHA1 signature.
88
89         @type bytes: str or L{array.array} of unsigned bytes
90         @param bytes: The value which will be hashed and verified.
91
92         @rtype: bool
93         @return: Whether the signature matches the passed-in data.
94         """
95         if not isinstance(bytes, type("")):
96             bytes = bytesToString(bytes)
97         hashBytes = stringToBytes(sha.sha(bytes).digest())
98         prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes)
99         return self.verify(sigBytes, prefixedHashBytes)
100
101     def sign(self, bytes):
102         """Sign the passed-in bytes.
103
104         This requires the key to have a private component.  It performs
105         a PKCS1 signature on the passed-in data.
106
107         @type bytes: L{array.array} of unsigned bytes
108         @param bytes: The value which will be signed.
109
110         @rtype: L{array.array} of unsigned bytes.
111         @return: A PKCS1 signature on the passed-in data.
112         """
113         if not self.hasPrivateKey():
114             raise AssertionError()
115         paddedBytes = self._addPKCS1Padding(bytes, 1)
116         m = bytesToNumber(paddedBytes)
117         if m >= self.n:
118             raise ValueError()
119         c = self._rawPrivateKeyOp(m)
120         sigBytes = numberToBytes(c)
121         return sigBytes
122
123     def verify(self, sigBytes, bytes):
124         """Verify the passed-in bytes with the signature.
125
126         This verifies a PKCS1 signature on the passed-in data.
127
128         @type sigBytes: L{array.array} of unsigned bytes
129         @param sigBytes: A PKCS1 signature.
130
131         @type bytes: L{array.array} of unsigned bytes
132         @param bytes: The value which will be verified.
133
134         @rtype: bool
135         @return: Whether the signature matches the passed-in data.
136         """
137         paddedBytes = self._addPKCS1Padding(bytes, 1)
138         c = bytesToNumber(sigBytes)
139         if c >= self.n:
140             return False
141         m = self._rawPublicKeyOp(c)
142         checkBytes = numberToBytes(m)
143         return checkBytes == paddedBytes
144
145     def encrypt(self, bytes):
146         """Encrypt the passed-in bytes.
147
148         This performs PKCS1 encryption of the passed-in data.
149
150         @type bytes: L{array.array} of unsigned bytes
151         @param bytes: The value which will be encrypted.
152
153         @rtype: L{array.array} of unsigned bytes.
154         @return: A PKCS1 encryption of the passed-in data.
155         """
156         paddedBytes = self._addPKCS1Padding(bytes, 2)
157         m = bytesToNumber(paddedBytes)
158         if m >= self.n:
159             raise ValueError()
160         c = self._rawPublicKeyOp(m)
161         encBytes = numberToBytes(c)
162         return encBytes
163
164     def decrypt(self, encBytes):
165         """Decrypt the passed-in bytes.
166
167         This requires the key to have a private component.  It performs
168         PKCS1 decryption of the passed-in data.
169
170         @type encBytes: L{array.array} of unsigned bytes
171         @param encBytes: The value which will be decrypted.
172
173         @rtype: L{array.array} of unsigned bytes or None.
174         @return: A PKCS1 decryption of the passed-in data or None if
175         the data is not properly formatted.
176         """
177         if not self.hasPrivateKey():
178             raise AssertionError()
179         c = bytesToNumber(encBytes)
180         if c >= self.n:
181             return None
182         m = self._rawPrivateKeyOp(c)
183         decBytes = numberToBytes(m)
184         if (len(decBytes) != numBytes(self.n)-1): #Check first byte
185             return None
186         if decBytes[0] != 2: #Check second byte
187             return None
188         for x in range(len(decBytes)-1): #Scan through for zero separator
189             if decBytes[x]== 0:
190                 break
191         else:
192             return None
193         return decBytes[x+1:] #Return everything after the separator
194
195     def _rawPrivateKeyOp(self, m):
196         raise NotImplementedError()
197
198     def _rawPublicKeyOp(self, c):
199         raise NotImplementedError()
200
201     def acceptsPassword(self):
202         """Return True if the write() method accepts a password for use
203         in encrypting the private key.
204
205         @rtype: bool
206         """
207         raise NotImplementedError()
208
209     def write(self, password=None):
210         """Return a string containing the key.
211
212         @rtype: str
213         @return: A string describing the key, in whichever format (PEM
214         or XML) is native to the implementation.
215         """
216         raise NotImplementedError()
217
218     def writeXMLPublicKey(self, indent=''):
219         """Return a string containing the key.
220
221         @rtype: str
222         @return: A string describing the public key, in XML format.
223         """
224         return Python_RSAKey(self.n, self.e).write(indent)
225
226     def generate(bits):
227         """Generate a new key with the specified bit length.
228
229         @rtype: L{tlslite.utils.RSAKey.RSAKey}
230         """
231         raise NotImplementedError()
232     generate = staticmethod(generate)
233
234
235     # **************************************************************************
236     # Helper Functions for RSA Keys
237     # **************************************************************************
238
239     def _addPKCS1SHA1Prefix(self, bytes):
240         prefixBytes = createByteArraySequence(\
241             [48,33,48,9,6,5,43,14,3,2,26,5,0,4,20])
242         prefixedBytes = prefixBytes + bytes
243         return prefixedBytes
244
245     def _addPKCS1Padding(self, bytes, blockType):
246         padLength = (numBytes(self.n) - (len(bytes)+3))
247         if blockType == 1: #Signature padding
248             pad = [0xFF] * padLength
249         elif blockType == 2: #Encryption padding
250             pad = createByteArraySequence([])
251             while len(pad) < padLength:
252                 padBytes = getRandomBytes(padLength * 2)
253                 pad = [b for b in padBytes if b != 0]
254                 pad = pad[:padLength]
255         else:
256             raise AssertionError()
257
258         #NOTE: To be proper, we should add [0,blockType].  However,
259         #the zero is lost when the returned padding is converted
260         #to a number, so we don't even bother with it.  Also,
261         #adding it would cause a misalignment in verify()
262         padding = createByteArraySequence([blockType] + pad + [0])
263         paddedBytes = padding + bytes
264         return paddedBytes