PageRenderTime 35ms CodeModel.GetById 21ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/gdata/tlslite/utils/RSAKey.py

http://radioappz.googlecode.com/
Python | 264 lines | 249 code | 3 blank | 12 comment | 0 complexity | a283269588835f9b2756b0b2217875fe MD5 | raw file
  1"""Abstract class for RSA."""
  2
  3from cryptomath import *
  4
  5
  6class 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(sha1(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(sha1(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