- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / utils / keyfactory.py
1 """Factory functions for asymmetric cryptography.
2 @sort: generateRSAKey, parseXMLKey, parsePEMKey, parseAsPublicKey,
3 parseAsPrivateKey
4 """
5
6 from compat import *
7
8 from RSAKey import RSAKey
9 from Python_RSAKey import Python_RSAKey
10 import cryptomath
11
12 if cryptomath.m2cryptoLoaded:
13     from OpenSSL_RSAKey import OpenSSL_RSAKey
14
15 if cryptomath.pycryptoLoaded:
16     from PyCrypto_RSAKey import PyCrypto_RSAKey
17
18 # **************************************************************************
19 # Factory Functions for RSA Keys
20 # **************************************************************************
21
22 def generateRSAKey(bits, implementations=["openssl", "python"]):
23     """Generate an RSA key with the specified bit length.
24
25     @type bits: int
26     @param bits: Desired bit length of the new key's modulus.
27
28     @rtype: L{tlslite.utils.RSAKey.RSAKey}
29     @return: A new RSA private key.
30     """
31     for implementation in implementations:
32         if implementation == "openssl" and cryptomath.m2cryptoLoaded:
33             return OpenSSL_RSAKey.generate(bits)
34         elif implementation == "python":
35             return Python_RSAKey.generate(bits)
36     raise ValueError("No acceptable implementations")
37
38 def parseXMLKey(s, private=False, public=False, implementations=["python"]):
39     """Parse an XML-format key.
40
41     The XML format used here is specific to tlslite and cryptoIDlib.  The
42     format can store the public component of a key, or the public and
43     private components.  For example::
44
45         <publicKey xmlns="http://trevp.net/rsa">
46             <n>4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pou...
47             <e>Aw==</e>
48         </publicKey>
49
50         <privateKey xmlns="http://trevp.net/rsa">
51             <n>4a5yzB8oGNlHo866CAspAC47M4Fvx58zwK8pou...
52             <e>Aw==</e>
53             <d>JZ0TIgUxWXmL8KJ0VqyG1V0J3ern9pqIoB0xmy...
54             <p>5PreIj6z6ldIGL1V4+1C36dQFHNCQHJvW52GXc...
55             <q>/E/wDit8YXPCxx126zTq2ilQ3IcW54NJYyNjiZ...
56             <dP>mKc+wX8inDowEH45Qp4slRo1YveBgExKPROu6...
57             <dQ>qDVKtBz9lk0shL5PR3ickXDgkwS576zbl2ztB...
58             <qInv>j6E8EA7dNsTImaXexAmLA1DoeArsYeFAInr...
59         </privateKey>
60
61     @type s: str
62     @param s: A string containing an XML public or private key.
63
64     @type private: bool
65     @param private: If True, a L{SyntaxError} will be raised if the private
66     key component is not present.
67
68     @type public: bool
69     @param public: If True, the private key component (if present) will be
70     discarded, so this function will always return a public key.
71
72     @rtype: L{tlslite.utils.RSAKey.RSAKey}
73     @return: An RSA key.
74
75     @raise SyntaxError: If the key is not properly formatted.
76     """
77     for implementation in implementations:
78         if implementation == "python":
79             key = Python_RSAKey.parseXML(s)
80             break
81     else:
82         raise ValueError("No acceptable implementations")
83
84     return _parseKeyHelper(key, private, public)
85
86 #Parse as an OpenSSL or Python key
87 def parsePEMKey(s, private=False, public=False, passwordCallback=None,
88                 implementations=["openssl", "python"]):
89     """Parse a PEM-format key.
90
91     The PEM format is used by OpenSSL and other tools.  The
92     format is typically used to store both the public and private
93     components of a key.  For example::
94
95        -----BEGIN RSA PRIVATE KEY-----
96         MIICXQIBAAKBgQDYscuoMzsGmW0pAYsmyHltxB2TdwHS0dImfjCMfaSDkfLdZY5+
97         dOWORVns9etWnr194mSGA1F0Pls/VJW8+cX9+3vtJV8zSdANPYUoQf0TP7VlJxkH
98         dSRkUbEoz5bAAs/+970uos7n7iXQIni+3erUTdYEk2iWnMBjTljfgbK/dQIDAQAB
99         AoGAJHoJZk75aKr7DSQNYIHuruOMdv5ZeDuJvKERWxTrVJqE32/xBKh42/IgqRrc
100         esBN9ZregRCd7YtxoL+EVUNWaJNVx2mNmezEznrc9zhcYUrgeaVdFO2yBF1889zO
101         gCOVwrO8uDgeyj6IKa25H6c1N13ih/o7ZzEgWbGG+ylU1yECQQDv4ZSJ4EjSh/Fl
102         aHdz3wbBa/HKGTjC8iRy476Cyg2Fm8MZUe9Yy3udOrb5ZnS2MTpIXt5AF3h2TfYV
103         VoFXIorjAkEA50FcJmzT8sNMrPaV8vn+9W2Lu4U7C+K/O2g1iXMaZms5PC5zV5aV
104         CKXZWUX1fq2RaOzlbQrpgiolhXpeh8FjxwJBAOFHzSQfSsTNfttp3KUpU0LbiVvv
105         i+spVSnA0O4rq79KpVNmK44Mq67hsW1P11QzrzTAQ6GVaUBRv0YS061td1kCQHnP
106         wtN2tboFR6lABkJDjxoGRvlSt4SOPr7zKGgrWjeiuTZLHXSAnCY+/hr5L9Q3ZwXG
107         6x6iBdgLjVIe4BZQNtcCQQDXGv/gWinCNTN3MPWfTW/RGzuMYVmyBFais0/VrgdH
108         h1dLpztmpQqfyH/zrBXQ9qL/zR4ojS6XYneO/U18WpEe
109         -----END RSA PRIVATE KEY-----
110
111     To generate a key like this with OpenSSL, run::
112
113         openssl genrsa 2048 > key.pem
114
115     This format also supports password-encrypted private keys.  TLS
116     Lite can only handle password-encrypted private keys when OpenSSL
117     and M2Crypto are installed.  In this case, passwordCallback will be
118     invoked to query the user for the password.
119
120     @type s: str
121     @param s: A string containing a PEM-encoded public or private key.
122
123     @type private: bool
124     @param private: If True, a L{SyntaxError} will be raised if the
125     private key component is not present.
126
127     @type public: bool
128     @param public: If True, the private key component (if present) will
129     be discarded, so this function will always return a public key.
130
131     @type passwordCallback: callable
132     @param passwordCallback: This function will be called, with no
133     arguments, if the PEM-encoded private key is password-encrypted.
134     The callback should return the password string.  If the password is
135     incorrect, SyntaxError will be raised.  If no callback is passed
136     and the key is password-encrypted, a prompt will be displayed at
137     the console.
138
139     @rtype: L{tlslite.utils.RSAKey.RSAKey}
140     @return: An RSA key.
141
142     @raise SyntaxError: If the key is not properly formatted.
143     """
144     for implementation in implementations:
145         if implementation == "openssl" and cryptomath.m2cryptoLoaded:
146             key = OpenSSL_RSAKey.parse(s, passwordCallback)
147             break
148         elif implementation == "python":
149             key = Python_RSAKey.parsePEM(s)
150             break
151     else:
152         raise ValueError("No acceptable implementations")
153
154     return _parseKeyHelper(key, private, public)
155
156
157 def _parseKeyHelper(key, private, public):
158     if private:
159         if not key.hasPrivateKey():
160             raise SyntaxError("Not a private key!")
161
162     if public:
163         return _createPublicKey(key)
164
165     if private:
166         if hasattr(key, "d"):
167             return _createPrivateKey(key)
168         else:
169             return key
170
171     return key
172
173 def parseAsPublicKey(s):
174     """Parse an XML or PEM-formatted public key.
175
176     @type s: str
177     @param s: A string containing an XML or PEM-encoded public or private key.
178
179     @rtype: L{tlslite.utils.RSAKey.RSAKey}
180     @return: An RSA public key.
181
182     @raise SyntaxError: If the key is not properly formatted.
183     """
184     try:
185         return parsePEMKey(s, public=True)
186     except:
187         return parseXMLKey(s, public=True)
188
189 def parsePrivateKey(s):
190     """Parse an XML or PEM-formatted private key.
191
192     @type s: str
193     @param s: A string containing an XML or PEM-encoded private key.
194
195     @rtype: L{tlslite.utils.RSAKey.RSAKey}
196     @return: An RSA private key.
197
198     @raise SyntaxError: If the key is not properly formatted.
199     """
200     try:
201         return parsePEMKey(s, private=True)
202     except:
203         return parseXMLKey(s, private=True)
204
205 def _createPublicKey(key):
206     """
207     Create a new public key.  Discard any private component,
208     and return the most efficient key possible.
209     """
210     if not isinstance(key, RSAKey):
211         raise AssertionError()
212     return _createPublicRSAKey(key.n, key.e)
213
214 def _createPrivateKey(key):
215     """
216     Create a new private key.  Return the most efficient key possible.
217     """
218     if not isinstance(key, RSAKey):
219         raise AssertionError()
220     if not key.hasPrivateKey():
221         raise AssertionError()
222     return _createPrivateRSAKey(key.n, key.e, key.d, key.p, key.q, key.dP,
223                                 key.dQ, key.qInv)
224
225 def _createPublicRSAKey(n, e, implementations = ["openssl", "pycrypto",
226                                                 "python"]):
227     for implementation in implementations:
228         if implementation == "openssl" and cryptomath.m2cryptoLoaded:
229             return OpenSSL_RSAKey(n, e)
230         elif implementation == "pycrypto" and cryptomath.pycryptoLoaded:
231             return PyCrypto_RSAKey(n, e)
232         elif implementation == "python":
233             return Python_RSAKey(n, e)
234     raise ValueError("No acceptable implementations")
235
236 def _createPrivateRSAKey(n, e, d, p, q, dP, dQ, qInv,
237                         implementations = ["pycrypto", "python"]):
238     for implementation in implementations:
239         if implementation == "pycrypto" and cryptomath.pycryptoLoaded:
240             return PyCrypto_RSAKey(n, e, d, p, q, dP, dQ, qInv)
241         elif implementation == "python":
242             return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
243     raise ValueError("No acceptable implementations")