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