_PBES.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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 Crypto.Util.py3compat import *
  34. from Crypto import Random
  35. from Crypto.Util.asn1 import (
  36. DerSequence, DerOctetString,
  37. DerObjectId, DerInteger,
  38. )
  39. from Crypto.Util.Padding import pad, unpad
  40. from Crypto.Hash import MD5, SHA1
  41. from Crypto.Cipher import DES, ARC2, DES3, AES
  42. from Crypto.Protocol.KDF import PBKDF1, PBKDF2, scrypt
  43. class PbesError(ValueError):
  44. pass
  45. # These are the ASN.1 definitions used by the PBES1/2 logic:
  46. #
  47. # EncryptedPrivateKeyInfo ::= SEQUENCE {
  48. # encryptionAlgorithm EncryptionAlgorithmIdentifier,
  49. # encryptedData EncryptedData
  50. # }
  51. #
  52. # EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  53. #
  54. # EncryptedData ::= OCTET STRING
  55. #
  56. # AlgorithmIdentifier ::= SEQUENCE {
  57. # algorithm OBJECT IDENTIFIER,
  58. # parameters ANY DEFINED BY algorithm OPTIONAL
  59. # }
  60. #
  61. # PBEParameter ::= SEQUENCE {
  62. # salt OCTET STRING (SIZE(8)),
  63. # iterationCount INTEGER
  64. # }
  65. #
  66. # PBES2-params ::= SEQUENCE {
  67. # keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
  68. # encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
  69. # }
  70. #
  71. # PBKDF2-params ::= SEQUENCE {
  72. # salt CHOICE {
  73. # specified OCTET STRING,
  74. # otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
  75. # },
  76. # iterationCount INTEGER (1..MAX),
  77. # keyLength INTEGER (1..MAX) OPTIONAL,
  78. # prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
  79. # }
  80. #
  81. # scrypt-params ::= SEQUENCE {
  82. # salt OCTET STRING,
  83. # costParameter INTEGER (1..MAX),
  84. # blockSize INTEGER (1..MAX),
  85. # parallelizationParameter INTEGER (1..MAX),
  86. # keyLength INTEGER (1..MAX) OPTIONAL
  87. # }
  88. class PBES1(object):
  89. """Deprecated encryption scheme with password-based key derivation
  90. (originally defined in PKCS#5 v1.5, but still present in `v2.0`__).
  91. .. __: http://www.ietf.org/rfc/rfc2898.txt
  92. """
  93. @staticmethod
  94. def decrypt(data, passphrase):
  95. """Decrypt a piece of data using a passphrase and *PBES1*.
  96. The algorithm to use is automatically detected.
  97. :Parameters:
  98. data : byte string
  99. The piece of data to decrypt.
  100. passphrase : byte string
  101. The passphrase to use for decrypting the data.
  102. :Returns:
  103. The decrypted data, as a binary string.
  104. """
  105. enc_private_key_info = DerSequence().decode(data)
  106. encrypted_algorithm = DerSequence().decode(enc_private_key_info[0])
  107. encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
  108. pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value
  109. cipher_params = {}
  110. if pbe_oid == "1.2.840.113549.1.5.3":
  111. # PBE_MD5_DES_CBC
  112. hashmod = MD5
  113. ciphermod = DES
  114. elif pbe_oid == "1.2.840.113549.1.5.6":
  115. # PBE_MD5_RC2_CBC
  116. hashmod = MD5
  117. ciphermod = ARC2
  118. cipher_params['effective_keylen'] = 64
  119. elif pbe_oid == "1.2.840.113549.1.5.10":
  120. # PBE_SHA1_DES_CBC
  121. hashmod = SHA1
  122. ciphermod = DES
  123. elif pbe_oid == "1.2.840.113549.1.5.11":
  124. # PBE_SHA1_RC2_CBC
  125. hashmod = SHA1
  126. ciphermod = ARC2
  127. cipher_params['effective_keylen'] = 64
  128. else:
  129. raise PbesError("Unknown OID for PBES1")
  130. pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2)
  131. salt = DerOctetString().decode(pbe_params[0]).payload
  132. iterations = pbe_params[1]
  133. key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod)
  134. key, iv = key_iv[:8], key_iv[8:]
  135. cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
  136. pt = cipher.decrypt(encrypted_data)
  137. return unpad(pt, cipher.block_size)
  138. class PBES2(object):
  139. """Encryption scheme with password-based key derivation
  140. (defined in `PKCS#5 v2.0`__).
  141. .. __: http://www.ietf.org/rfc/rfc2898.txt."""
  142. @staticmethod
  143. def encrypt(data, passphrase, protection, prot_params=None, randfunc=None):
  144. """Encrypt a piece of data using a passphrase and *PBES2*.
  145. :Parameters:
  146. data : byte string
  147. The piece of data to encrypt.
  148. passphrase : byte string
  149. The passphrase to use for encrypting the data.
  150. protection : string
  151. The identifier of the encryption algorithm to use.
  152. The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'.
  153. prot_params : dictionary
  154. Parameters of the protection algorithm.
  155. +------------------+-----------------------------------------------+
  156. | Key | Description |
  157. +==================+===============================================+
  158. | iteration_count | The KDF algorithm is repeated several times to|
  159. | | slow down brute force attacks on passwords |
  160. | | (called *N* or CPU/memory cost in scrypt). |
  161. | | |
  162. | | The default value for PBKDF2 is 1 000. |
  163. | | The default value for scrypt is 16 384. |
  164. +------------------+-----------------------------------------------+
  165. | salt_size | Salt is used to thwart dictionary and rainbow |
  166. | | attacks on passwords. The default value is 8 |
  167. | | bytes. |
  168. +------------------+-----------------------------------------------+
  169. | block_size | *(scrypt only)* Memory-cost (r). The default |
  170. | | value is 8. |
  171. +------------------+-----------------------------------------------+
  172. | parallelization | *(scrypt only)* CPU-cost (p). The default |
  173. | | value is 1. |
  174. +------------------+-----------------------------------------------+
  175. randfunc : callable
  176. Random number generation function; it should accept
  177. a single integer N and return a string of random data,
  178. N bytes long. If not specified, a new RNG will be
  179. instantiated from ``Crypto.Random``.
  180. :Returns:
  181. The encrypted data, as a binary string.
  182. """
  183. if prot_params is None:
  184. prot_params = {}
  185. if randfunc is None:
  186. randfunc = Random.new().read
  187. if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC':
  188. key_size = 24
  189. module = DES3
  190. cipher_mode = DES3.MODE_CBC
  191. enc_oid = "1.2.840.113549.3.7"
  192. elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC',
  193. 'scryptAndAES128-CBC'):
  194. key_size = 16
  195. module = AES
  196. cipher_mode = AES.MODE_CBC
  197. enc_oid = "2.16.840.1.101.3.4.1.2"
  198. elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC',
  199. 'scryptAndAES192-CBC'):
  200. key_size = 24
  201. module = AES
  202. cipher_mode = AES.MODE_CBC
  203. enc_oid = "2.16.840.1.101.3.4.1.22"
  204. elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC',
  205. 'scryptAndAES256-CBC'):
  206. key_size = 32
  207. module = AES
  208. cipher_mode = AES.MODE_CBC
  209. enc_oid = "2.16.840.1.101.3.4.1.42"
  210. else:
  211. raise ValueError("Unknown PBES2 mode")
  212. # Get random data
  213. iv = randfunc(module.block_size)
  214. salt = randfunc(prot_params.get("salt_size", 8))
  215. # Derive key from password
  216. if protection.startswith('PBKDF2'):
  217. count = prot_params.get("iteration_count", 1000)
  218. key = PBKDF2(passphrase, salt, key_size, count)
  219. kdf_info = DerSequence([
  220. DerObjectId("1.2.840.113549.1.5.12"), # PBKDF2
  221. DerSequence([
  222. DerOctetString(salt),
  223. DerInteger(count)
  224. ])
  225. ])
  226. else:
  227. # It must be scrypt
  228. count = prot_params.get("iteration_count", 16384)
  229. scrypt_r = prot_params.get('block_size', 8)
  230. scrypt_p = prot_params.get('parallelization', 1)
  231. key = scrypt(passphrase, salt, key_size,
  232. count, scrypt_r, scrypt_p)
  233. kdf_info = DerSequence([
  234. DerObjectId("1.3.6.1.4.1.11591.4.11"), # scrypt
  235. DerSequence([
  236. DerOctetString(salt),
  237. DerInteger(count),
  238. DerInteger(scrypt_r),
  239. DerInteger(scrypt_p)
  240. ])
  241. ])
  242. # Create cipher and use it
  243. cipher = module.new(key, cipher_mode, iv)
  244. encrypted_data = cipher.encrypt(pad(data, cipher.block_size))
  245. enc_info = DerSequence([
  246. DerObjectId(enc_oid),
  247. DerOctetString(iv)
  248. ])
  249. # Result
  250. enc_private_key_info = DerSequence([
  251. # encryptionAlgorithm
  252. DerSequence([
  253. DerObjectId("1.2.840.113549.1.5.13"), # PBES2
  254. DerSequence([
  255. kdf_info,
  256. enc_info
  257. ]),
  258. ]),
  259. DerOctetString(encrypted_data)
  260. ])
  261. return enc_private_key_info.encode()
  262. @staticmethod
  263. def decrypt(data, passphrase):
  264. """Decrypt a piece of data using a passphrase and *PBES2*.
  265. The algorithm to use is automatically detected.
  266. :Parameters:
  267. data : byte string
  268. The piece of data to decrypt.
  269. passphrase : byte string
  270. The passphrase to use for decrypting the data.
  271. :Returns:
  272. The decrypted data, as a binary string.
  273. """
  274. enc_private_key_info = DerSequence().decode(data, nr_elements=2)
  275. enc_algo = DerSequence().decode(enc_private_key_info[0])
  276. encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
  277. pbe_oid = DerObjectId().decode(enc_algo[0]).value
  278. if pbe_oid != "1.2.840.113549.1.5.13":
  279. raise PbesError("Not a PBES2 object")
  280. pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2)
  281. ### Key Derivation Function selection
  282. kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2)
  283. kdf_oid = DerObjectId().decode(kdf_info[0]).value
  284. # We only support PBKDF2 or scrypt
  285. if kdf_oid == "1.2.840.113549.1.5.12":
  286. pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4))
  287. salt = DerOctetString().decode(pbkdf2_params[0]).payload
  288. iteration_count = pbkdf2_params[1]
  289. if len(pbkdf2_params) > 2:
  290. kdf_key_length = pbkdf2_params[2]
  291. else:
  292. kdf_key_length = None
  293. if len(pbkdf2_params) > 3:
  294. raise PbesError("Unsupported PRF for PBKDF2")
  295. elif kdf_oid == "1.3.6.1.4.1.11591.4.11":
  296. scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5))
  297. salt = DerOctetString().decode(scrypt_params[0]).payload
  298. iteration_count, scrypt_r, scrypt_p = [scrypt_params[x]
  299. for x in (1, 2, 3)]
  300. if len(scrypt_params) > 4:
  301. kdf_key_length = scrypt_params[4]
  302. else:
  303. kdf_key_length = None
  304. else:
  305. raise PbesError("Unsupported PBES2 KDF")
  306. ### Cipher selection
  307. enc_info = DerSequence().decode(pbes2_params[1])
  308. enc_oid = DerObjectId().decode(enc_info[0]).value
  309. if enc_oid == "1.2.840.113549.3.7":
  310. # DES_EDE3_CBC
  311. ciphermod = DES3
  312. key_size = 24
  313. elif enc_oid == "2.16.840.1.101.3.4.1.2":
  314. # AES128_CBC
  315. ciphermod = AES
  316. key_size = 16
  317. elif enc_oid == "2.16.840.1.101.3.4.1.22":
  318. # AES192_CBC
  319. ciphermod = AES
  320. key_size = 24
  321. elif enc_oid == "2.16.840.1.101.3.4.1.42":
  322. # AES256_CBC
  323. ciphermod = AES
  324. key_size = 32
  325. else:
  326. raise PbesError("Unsupported PBES2 cipher")
  327. if kdf_key_length and kdf_key_length != key_size:
  328. raise PbesError("Mismatch between PBES2 KDF parameters"
  329. " and selected cipher")
  330. IV = DerOctetString().decode(enc_info[1]).payload
  331. # Create cipher
  332. if kdf_oid == "1.2.840.113549.1.5.12": # PBKDF2
  333. key = PBKDF2(passphrase, salt, key_size, iteration_count)
  334. else:
  335. key = scrypt(passphrase, salt, key_size, iteration_count,
  336. scrypt_r, scrypt_p)
  337. cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV)
  338. # Decrypt data
  339. pt = cipher.decrypt(encrypted_data)
  340. return unpad(pt, cipher.block_size)