• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Author: Trevor Perrin
2# See the LICENSE file for legal information regarding use of this file.
3
4"""Abstract class for RSA."""
5
6from .cryptomath import *
7
8
9class RSAKey(object):
10    """This is an abstract base class for RSA keys.
11
12    Particular implementations of RSA keys, such as
13    L{openssl_rsakey.OpenSSL_RSAKey},
14    L{python_rsakey.Python_RSAKey}, and
15    L{pycrypto_rsakey.PyCrypto_RSAKey},
16    inherit from this.
17
18    To create or parse an RSA key, don't use one of these classes
19    directly.  Instead, use the factory functions in
20    L{tlslite.utils.keyfactory}.
21    """
22
23    def __init__(self, n=0, e=0):
24        """Create a new RSA key.
25
26        If n and e are passed in, the new key will be initialized.
27
28        @type n: int
29        @param n: RSA modulus.
30
31        @type e: int
32        @param e: RSA public exponent.
33        """
34        raise NotImplementedError()
35
36    def __len__(self):
37        """Return the length of this key in bits.
38
39        @rtype: int
40        """
41        return numBits(self.n)
42
43    def hasPrivateKey(self):
44        """Return whether or not this key has a private component.
45
46        @rtype: bool
47        """
48        raise NotImplementedError()
49
50    def hashAndSign(self, bytes):
51        """Hash and sign the passed-in bytes.
52
53        This requires the key to have a private component.  It performs
54        a PKCS1-SHA1 signature on the passed-in data.
55
56        @type bytes: str or L{bytearray} of unsigned bytes
57        @param bytes: The value which will be hashed and signed.
58
59        @rtype: L{bytearray} of unsigned bytes.
60        @return: A PKCS1-SHA1 signature on the passed-in data.
61        """
62        hashBytes = SHA1(bytearray(bytes))
63        prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes)
64        sigBytes = self.sign(prefixedHashBytes)
65        return sigBytes
66
67    def hashAndVerify(self, sigBytes, bytes):
68        """Hash and verify the passed-in bytes with the signature.
69
70        This verifies a PKCS1-SHA1 signature on the passed-in data.
71
72        @type sigBytes: L{bytearray} of unsigned bytes
73        @param sigBytes: A PKCS1-SHA1 signature.
74
75        @type bytes: str or L{bytearray} of unsigned bytes
76        @param bytes: The value which will be hashed and verified.
77
78        @rtype: bool
79        @return: Whether the signature matches the passed-in data.
80        """
81        hashBytes = SHA1(bytearray(bytes))
82
83        # Try it with/without the embedded NULL
84        prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False)
85        prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True)
86        result1 = self.verify(sigBytes, prefixedHashBytes1)
87        result2 = self.verify(sigBytes, prefixedHashBytes2)
88        return (result1 or result2)
89
90    def sign(self, bytes):
91        """Sign the passed-in bytes.
92
93        This requires the key to have a private component.  It performs
94        a PKCS1 signature on the passed-in data.
95
96        @type bytes: L{bytearray} of unsigned bytes
97        @param bytes: The value which will be signed.
98
99        @rtype: L{bytearray} of unsigned bytes.
100        @return: A PKCS1 signature on the passed-in data.
101        """
102        if not self.hasPrivateKey():
103            raise AssertionError()
104        paddedBytes = self._addPKCS1Padding(bytes, 1)
105        m = bytesToNumber(paddedBytes)
106        if m >= self.n:
107            raise ValueError()
108        c = self._rawPrivateKeyOp(m)
109        sigBytes = numberToByteArray(c, numBytes(self.n))
110        return sigBytes
111
112    def verify(self, sigBytes, bytes):
113        """Verify the passed-in bytes with the signature.
114
115        This verifies a PKCS1 signature on the passed-in data.
116
117        @type sigBytes: L{bytearray} of unsigned bytes
118        @param sigBytes: A PKCS1 signature.
119
120        @type bytes: L{bytearray} of unsigned bytes
121        @param bytes: The value which will be verified.
122
123        @rtype: bool
124        @return: Whether the signature matches the passed-in data.
125        """
126        if len(sigBytes) != numBytes(self.n):
127            return False
128        paddedBytes = self._addPKCS1Padding(bytes, 1)
129        c = bytesToNumber(sigBytes)
130        if c >= self.n:
131            return False
132        m = self._rawPublicKeyOp(c)
133        checkBytes = numberToByteArray(m, numBytes(self.n))
134        return checkBytes == paddedBytes
135
136    def encrypt(self, bytes):
137        """Encrypt the passed-in bytes.
138
139        This performs PKCS1 encryption of the passed-in data.
140
141        @type bytes: L{bytearray} of unsigned bytes
142        @param bytes: The value which will be encrypted.
143
144        @rtype: L{bytearray} of unsigned bytes.
145        @return: A PKCS1 encryption of the passed-in data.
146        """
147        paddedBytes = self._addPKCS1Padding(bytes, 2)
148        m = bytesToNumber(paddedBytes)
149        if m >= self.n:
150            raise ValueError()
151        c = self._rawPublicKeyOp(m)
152        encBytes = numberToByteArray(c, numBytes(self.n))
153        return encBytes
154
155    def decrypt(self, encBytes):
156        """Decrypt the passed-in bytes.
157
158        This requires the key to have a private component.  It performs
159        PKCS1 decryption of the passed-in data.
160
161        @type encBytes: L{bytearray} of unsigned bytes
162        @param encBytes: The value which will be decrypted.
163
164        @rtype: L{bytearray} of unsigned bytes or None.
165        @return: A PKCS1 decryption of the passed-in data or None if
166        the data is not properly formatted.
167        """
168        if not self.hasPrivateKey():
169            raise AssertionError()
170        if len(encBytes) != numBytes(self.n):
171            return None
172        c = bytesToNumber(encBytes)
173        if c >= self.n:
174            return None
175        m = self._rawPrivateKeyOp(c)
176        decBytes = numberToByteArray(m, numBytes(self.n))
177        #Check first two bytes
178        if decBytes[0] != 0 or decBytes[1] != 2:
179            return None
180        #Scan through for zero separator
181        for x in range(1, len(decBytes)-1):
182            if decBytes[x]== 0:
183                break
184        else:
185            return None
186        return decBytes[x+1:] #Return everything after the separator
187
188    def _rawPrivateKeyOp(self, m):
189        raise NotImplementedError()
190
191    def _rawPublicKeyOp(self, c):
192        raise NotImplementedError()
193
194    def acceptsPassword(self):
195        """Return True if the write() method accepts a password for use
196        in encrypting the private key.
197
198        @rtype: bool
199        """
200        raise NotImplementedError()
201
202    def write(self, password=None):
203        """Return a string containing the key.
204
205        @rtype: str
206        @return: A string describing the key, in whichever format (PEM)
207        is native to the implementation.
208        """
209        raise NotImplementedError()
210
211    def generate(bits):
212        """Generate a new key with the specified bit length.
213
214        @rtype: L{tlslite.utils.RSAKey.RSAKey}
215        """
216        raise NotImplementedError()
217    generate = staticmethod(generate)
218
219
220    # **************************************************************************
221    # Helper Functions for RSA Keys
222    # **************************************************************************
223
224    def _addPKCS1SHA1Prefix(self, bytes, withNULL=True):
225        # There is a long history of confusion over whether the SHA1
226        # algorithmIdentifier should be encoded with a NULL parameter or
227        # with the parameter omitted.  While the original intention was
228        # apparently to omit it, many toolkits went the other way.  TLS 1.2
229        # specifies the NULL should be included, and this behavior is also
230        # mandated in recent versions of PKCS #1, and is what tlslite has
231        # always implemented.  Anyways, verification code should probably
232        # accept both.  However, nothing uses this code yet, so this is
233        # all fairly moot.
234        if not withNULL:
235            prefixBytes = bytearray(\
236            [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])
237        else:
238            prefixBytes = bytearray(\
239            [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14])
240        prefixedBytes = prefixBytes + bytes
241        return prefixedBytes
242
243    def _addPKCS1Padding(self, bytes, blockType):
244        padLength = (numBytes(self.n) - (len(bytes)+3))
245        if blockType == 1: #Signature padding
246            pad = [0xFF] * padLength
247        elif blockType == 2: #Encryption padding
248            pad = bytearray(0)
249            while len(pad) < padLength:
250                padBytes = getRandomBytes(padLength * 2)
251                pad = [b for b in padBytes if b != 0]
252                pad = pad[:padLength]
253        else:
254            raise AssertionError()
255
256        padding = bytearray([0,blockType] + pad + [0])
257        paddedBytes = padding + bytes
258        return paddedBytes
259