/gdata/tlslite/utils/RSAKey.py

http://radioappz.googlecode.com/ · Python · 264 lines · 135 code · 32 blank · 97 comment · 16 complexity · a283269588835f9b2756b0b2217875fe MD5 · raw file

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