_PBES.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #
  2. # PublicKey/_PBES.py : Password-Based Encryption functions
  3. #
  4. # ===================================================================
  5. #
  6. # Copyright (c) 2014, Legrandin <helderijs@gmail.com>
  7. # All rights reserved.
  8. #
  9. # Redistribution and use in source and binary forms, with or without
  10. # modification, are permitted provided that the following conditions
  11. # are met:
  12. #
  13. # 1. Redistributions of source code must retain the above copyright
  14. # notice, this list of conditions and the following disclaimer.
  15. # 2. Redistributions in binary form must reproduce the above copyright
  16. # notice, this list of conditions and the following disclaimer in
  17. # the documentation and/or other materials provided with the
  18. # distribution.
  19. #
  20. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  28. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  30. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. # POSSIBILITY OF SUCH DAMAGE.
  32. # ===================================================================
  33. from tls.Crypto import Random
  34. from tls.Crypto.Util.asn1 import (
  35. DerSequence, DerOctetString,
  36. DerObjectId, DerInteger,
  37. )
  38. from tls.Crypto.Util.Padding import pad, unpad
  39. from tls.Crypto.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512
  40. from tls.Crypto.Cipher import DES, ARC2, DES3, AES
  41. from tls.Crypto.Protocol.KDF import PBKDF1, PBKDF2, scrypt
  42. _OID_PBE_WITH_MD5_AND_DES_CBC = "1.2.840.113549.1.5.3"
  43. _OID_PBE_WITH_MD5_AND_RC2_CBC = "1.2.840.113549.1.5.6"
  44. _OID_PBE_WITH_SHA1_AND_DES_CBC = "1.2.840.113549.1.5.10"
  45. _OID_PBE_WITH_SHA1_AND_RC2_CBC = "1.2.840.113549.1.5.11"
  46. _OID_PBES2 = "1.2.840.113549.1.5.13"
  47. _OID_PBKDF2 = "1.2.840.113549.1.5.12"
  48. _OID_SCRYPT = "1.3.6.1.4.1.11591.4.11"
  49. _OID_HMAC_SHA1 = "1.2.840.113549.2.7"
  50. _OID_HMAC_SHA224 = "1.2.840.113549.2.8"
  51. _OID_HMAC_SHA256 = "1.2.840.113549.2.9"
  52. _OID_HMAC_SHA384 = "1.2.840.113549.2.10"
  53. _OID_HMAC_SHA512 = "1.2.840.113549.2.11"
  54. _OID_DES_EDE3_CBC = "1.2.840.113549.3.7"
  55. _OID_AES128_CBC = "2.16.840.1.101.3.4.1.2"
  56. _OID_AES192_CBC = "2.16.840.1.101.3.4.1.22"
  57. _OID_AES256_CBC = "2.16.840.1.101.3.4.1.42"
  58. class PbesError(ValueError):
  59. pass
  60. # These are the ASN.1 definitions used by the PBES1/2 logic:
  61. #
  62. # EncryptedPrivateKeyInfo ::= SEQUENCE {
  63. # encryptionAlgorithm EncryptionAlgorithmIdentifier,
  64. # encryptedData EncryptedData
  65. # }
  66. #
  67. # EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  68. #
  69. # EncryptedData ::= OCTET STRING
  70. #
  71. # AlgorithmIdentifier ::= SEQUENCE {
  72. # algorithm OBJECT IDENTIFIER,
  73. # parameters ANY DEFINED BY algorithm OPTIONAL
  74. # }
  75. #
  76. # PBEParameter ::= SEQUENCE {
  77. # salt OCTET STRING (SIZE(8)),
  78. # iterationCount INTEGER
  79. # }
  80. #
  81. # PBES2-params ::= SEQUENCE {
  82. # keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
  83. # encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
  84. # }
  85. #
  86. # PBKDF2-params ::= SEQUENCE {
  87. # salt CHOICE {
  88. # specified OCTET STRING,
  89. # otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
  90. # },
  91. # iterationCount INTEGER (1..MAX),
  92. # keyLength INTEGER (1..MAX) OPTIONAL,
  93. # prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
  94. # }
  95. #
  96. # scrypt-params ::= SEQUENCE {
  97. # salt OCTET STRING,
  98. # costParameter INTEGER (1..MAX),
  99. # blockSize INTEGER (1..MAX),
  100. # parallelizationParameter INTEGER (1..MAX),
  101. # keyLength INTEGER (1..MAX) OPTIONAL
  102. # }
  103. class PBES1(object):
  104. """Deprecated encryption scheme with password-based key derivation
  105. (originally defined in PKCS#5 v1.5, but still present in `v2.0`__).
  106. .. __: http://www.ietf.org/rfc/rfc2898.txt
  107. """
  108. @staticmethod
  109. def decrypt(data, passphrase):
  110. """Decrypt a piece of data using a passphrase and *PBES1*.
  111. The algorithm to use is automatically detected.
  112. :Parameters:
  113. data : byte string
  114. The piece of data to decrypt.
  115. passphrase : byte string
  116. The passphrase to use for decrypting the data.
  117. :Returns:
  118. The decrypted data, as a binary string.
  119. """
  120. enc_private_key_info = DerSequence().decode(data)
  121. encrypted_algorithm = DerSequence().decode(enc_private_key_info[0])
  122. encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
  123. pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value
  124. cipher_params = {}
  125. if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC:
  126. # PBE_MD5_DES_CBC
  127. hashmod = MD5
  128. ciphermod = DES
  129. elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC:
  130. # PBE_MD5_RC2_CBC
  131. hashmod = MD5
  132. ciphermod = ARC2
  133. cipher_params['effective_keylen'] = 64
  134. elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC:
  135. # PBE_SHA1_DES_CBC
  136. hashmod = SHA1
  137. ciphermod = DES
  138. elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC:
  139. # PBE_SHA1_RC2_CBC
  140. hashmod = SHA1
  141. ciphermod = ARC2
  142. cipher_params['effective_keylen'] = 64
  143. else:
  144. raise PbesError("Unknown OID for PBES1")
  145. pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2)
  146. salt = DerOctetString().decode(pbe_params[0]).payload
  147. iterations = pbe_params[1]
  148. key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod)
  149. key, iv = key_iv[:8], key_iv[8:]
  150. cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
  151. pt = cipher.decrypt(encrypted_data)
  152. return unpad(pt, cipher.block_size)
  153. class PBES2(object):
  154. """Encryption scheme with password-based key derivation
  155. (defined in `PKCS#5 v2.0`__).
  156. .. __: http://www.ietf.org/rfc/rfc2898.txt."""
  157. @staticmethod
  158. def encrypt(data, passphrase, protection, prot_params=None, randfunc=None):
  159. """Encrypt a piece of data using a passphrase and *PBES2*.
  160. :Parameters:
  161. data : byte string
  162. The piece of data to encrypt.
  163. passphrase : byte string
  164. The passphrase to use for encrypting the data.
  165. protection : string
  166. The identifier of the encryption algorithm to use.
  167. The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'.
  168. prot_params : dictionary
  169. Parameters of the protection algorithm.
  170. +------------------+-----------------------------------------------+
  171. | Key | Description |
  172. +==================+===============================================+
  173. | iteration_count | The KDF algorithm is repeated several times to|
  174. | | slow down brute force attacks on passwords |
  175. | | (called *N* or CPU/memory cost in scrypt). |
  176. | | |
  177. | | The default value for PBKDF2 is 1 000. |
  178. | | The default value for scrypt is 16 384. |
  179. +------------------+-----------------------------------------------+
  180. | salt_size | Salt is used to thwart dictionary and rainbow |
  181. | | attacks on passwords. The default value is 8 |
  182. | | bytes. |
  183. +------------------+-----------------------------------------------+
  184. | block_size | *(scrypt only)* Memory-cost (r). The default |
  185. | | value is 8. |
  186. +------------------+-----------------------------------------------+
  187. | parallelization | *(scrypt only)* CPU-cost (p). The default |
  188. | | value is 1. |
  189. +------------------+-----------------------------------------------+
  190. randfunc : callable
  191. Random number generation function; it should accept
  192. a single integer N and return a string of random data,
  193. N bytes long. If not specified, a new RNG will be
  194. instantiated from ``Crypto.Random``.
  195. :Returns:
  196. The encrypted data, as a binary string.
  197. """
  198. if prot_params is None:
  199. prot_params = {}
  200. if randfunc is None:
  201. randfunc = Random.new().read
  202. if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC':
  203. key_size = 24
  204. module = DES3
  205. cipher_mode = DES3.MODE_CBC
  206. enc_oid = _OID_DES_EDE3_CBC
  207. elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC',
  208. 'scryptAndAES128-CBC'):
  209. key_size = 16
  210. module = AES
  211. cipher_mode = AES.MODE_CBC
  212. enc_oid = _OID_AES128_CBC
  213. elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC',
  214. 'scryptAndAES192-CBC'):
  215. key_size = 24
  216. module = AES
  217. cipher_mode = AES.MODE_CBC
  218. enc_oid = _OID_AES192_CBC
  219. elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC',
  220. 'scryptAndAES256-CBC'):
  221. key_size = 32
  222. module = AES
  223. cipher_mode = AES.MODE_CBC
  224. enc_oid = _OID_AES256_CBC
  225. else:
  226. raise ValueError("Unknown PBES2 mode")
  227. # Get random data
  228. iv = randfunc(module.block_size)
  229. salt = randfunc(prot_params.get("salt_size", 8))
  230. # Derive key from password
  231. if protection.startswith('PBKDF2'):
  232. count = prot_params.get("iteration_count", 1000)
  233. key = PBKDF2(passphrase, salt, key_size, count)
  234. kdf_info = DerSequence([
  235. DerObjectId(_OID_PBKDF2), # PBKDF2
  236. DerSequence([
  237. DerOctetString(salt),
  238. DerInteger(count)
  239. ])
  240. ])
  241. else:
  242. # It must be scrypt
  243. count = prot_params.get("iteration_count", 16384)
  244. scrypt_r = prot_params.get('block_size', 8)
  245. scrypt_p = prot_params.get('parallelization', 1)
  246. key = scrypt(passphrase, salt, key_size,
  247. count, scrypt_r, scrypt_p)
  248. kdf_info = DerSequence([
  249. DerObjectId(_OID_SCRYPT), # scrypt
  250. DerSequence([
  251. DerOctetString(salt),
  252. DerInteger(count),
  253. DerInteger(scrypt_r),
  254. DerInteger(scrypt_p)
  255. ])
  256. ])
  257. # Create cipher and use it
  258. cipher = module.new(key, cipher_mode, iv)
  259. encrypted_data = cipher.encrypt(pad(data, cipher.block_size))
  260. enc_info = DerSequence([
  261. DerObjectId(enc_oid),
  262. DerOctetString(iv)
  263. ])
  264. # Result
  265. enc_private_key_info = DerSequence([
  266. # encryptionAlgorithm
  267. DerSequence([
  268. DerObjectId(_OID_PBES2),
  269. DerSequence([
  270. kdf_info,
  271. enc_info
  272. ]),
  273. ]),
  274. DerOctetString(encrypted_data)
  275. ])
  276. return enc_private_key_info.encode()
  277. @staticmethod
  278. def decrypt(data, passphrase):
  279. """Decrypt a piece of data using a passphrase and *PBES2*.
  280. The algorithm to use is automatically detected.
  281. :Parameters:
  282. data : byte string
  283. The piece of data to decrypt.
  284. passphrase : byte string
  285. The passphrase to use for decrypting the data.
  286. :Returns:
  287. The decrypted data, as a binary string.
  288. """
  289. enc_private_key_info = DerSequence().decode(data, nr_elements=2)
  290. enc_algo = DerSequence().decode(enc_private_key_info[0])
  291. encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
  292. pbe_oid = DerObjectId().decode(enc_algo[0]).value
  293. if pbe_oid != _OID_PBES2:
  294. raise PbesError("Not a PBES2 object")
  295. pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2)
  296. ### Key Derivation Function selection
  297. kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2)
  298. kdf_oid = DerObjectId().decode(kdf_info[0]).value
  299. kdf_key_length = None
  300. # We only support PBKDF2 or scrypt
  301. if kdf_oid == _OID_PBKDF2:
  302. pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4))
  303. salt = DerOctetString().decode(pbkdf2_params[0]).payload
  304. iteration_count = pbkdf2_params[1]
  305. left = len(pbkdf2_params) - 2
  306. idx = 2
  307. if left > 0:
  308. try:
  309. kdf_key_length = pbkdf2_params[idx] - 0
  310. left -= 1
  311. idx += 1
  312. except TypeError:
  313. pass
  314. # Default is HMAC-SHA1
  315. pbkdf2_prf_oid = "1.2.840.113549.2.7"
  316. if left > 0:
  317. pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx])
  318. pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value
  319. elif kdf_oid == _OID_SCRYPT:
  320. scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5))
  321. salt = DerOctetString().decode(scrypt_params[0]).payload
  322. iteration_count, scrypt_r, scrypt_p = [scrypt_params[x]
  323. for x in (1, 2, 3)]
  324. if len(scrypt_params) > 4:
  325. kdf_key_length = scrypt_params[4]
  326. else:
  327. kdf_key_length = None
  328. else:
  329. raise PbesError("Unsupported PBES2 KDF")
  330. ### Cipher selection
  331. enc_info = DerSequence().decode(pbes2_params[1])
  332. enc_oid = DerObjectId().decode(enc_info[0]).value
  333. if enc_oid == _OID_DES_EDE3_CBC:
  334. # DES_EDE3_CBC
  335. ciphermod = DES3
  336. key_size = 24
  337. elif enc_oid == _OID_AES128_CBC:
  338. # AES128_CBC
  339. ciphermod = AES
  340. key_size = 16
  341. elif enc_oid == _OID_AES192_CBC:
  342. # AES192_CBC
  343. ciphermod = AES
  344. key_size = 24
  345. elif enc_oid == _OID_AES256_CBC:
  346. # AES256_CBC
  347. ciphermod = AES
  348. key_size = 32
  349. else:
  350. raise PbesError("Unsupported PBES2 cipher")
  351. if kdf_key_length and kdf_key_length != key_size:
  352. raise PbesError("Mismatch between PBES2 KDF parameters"
  353. " and selected cipher")
  354. IV = DerOctetString().decode(enc_info[1]).payload
  355. # Create cipher
  356. if kdf_oid == _OID_PBKDF2:
  357. if pbkdf2_prf_oid == _OID_HMAC_SHA1:
  358. hmac_hash_module = SHA1
  359. elif pbkdf2_prf_oid == _OID_HMAC_SHA224:
  360. hmac_hash_module = SHA224
  361. elif pbkdf2_prf_oid == _OID_HMAC_SHA256:
  362. hmac_hash_module = SHA256
  363. elif pbkdf2_prf_oid == _OID_HMAC_SHA384:
  364. hmac_hash_module = SHA384
  365. elif pbkdf2_prf_oid == _OID_HMAC_SHA512:
  366. hmac_hash_module = SHA512
  367. else:
  368. raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid)
  369. key = PBKDF2(passphrase, salt, key_size, iteration_count,
  370. hmac_hash_module=hmac_hash_module)
  371. else:
  372. key = scrypt(passphrase, salt, key_size, iteration_count,
  373. scrypt_r, scrypt_p)
  374. cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV)
  375. # Decrypt data
  376. pt = cipher.decrypt(encrypted_data)
  377. return unpad(pt, cipher.block_size)