]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/aes.py
1 from __future__
import unicode_literals
3 __all__
= ['aes_encrypt', 'key_expansion', 'aes_ctr_decrypt', 'aes_cbc_decrypt', 'aes_decrypt_text']
8 from .utils
import bytes_to_intlist
, intlist_to_bytes
13 def aes_ctr_decrypt(data
, key
, counter
):
15 Decrypt with aes in counter mode
17 @param {int[]} data cipher
18 @param {int[]} key 16/24/32-Byte cipher key
19 @param {instance} counter Instance whose next_value function (@returns {int[]} 16-Byte block)
20 returns the next counter block
21 @returns {int[]} decrypted data
23 expanded_key
= key_expansion(key
)
24 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
27 for i
in range(block_count
):
28 counter_block
= counter
.next_value()
29 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
30 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
32 cipher_counter_block
= aes_encrypt(counter_block
, expanded_key
)
33 decrypted_data
+= xor(block
, cipher_counter_block
)
34 decrypted_data
= decrypted_data
[:len(data
)]
39 def aes_cbc_decrypt(data
, key
, iv
):
41 Decrypt with aes in CBC mode
43 @param {int[]} data cipher
44 @param {int[]} key 16/24/32-Byte cipher key
45 @param {int[]} iv 16-Byte IV
46 @returns {int[]} decrypted data
48 expanded_key
= key_expansion(key
)
49 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
52 previous_cipher_block
= iv
53 for i
in range(block_count
):
54 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
55 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
57 decrypted_block
= aes_decrypt(block
, expanded_key
)
58 decrypted_data
+= xor(decrypted_block
, previous_cipher_block
)
59 previous_cipher_block
= block
60 decrypted_data
= decrypted_data
[:len(data
)]
65 def key_expansion(data
):
69 @param {int[]} data 16/24/32-Byte cipher key
70 @returns {int[]} 176/208/240-Byte expanded key
74 key_size_bytes
= len(data
)
75 expanded_key_size_bytes
= (key_size_bytes
// 4 + 7) * BLOCK_SIZE_BYTES
77 while len(data
) < expanded_key_size_bytes
:
79 temp
= key_schedule_core(temp
, rcon_iteration
)
81 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
85 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
87 if key_size_bytes
== 32:
89 temp
= sub_bytes(temp
)
90 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
92 for _
in range(3 if key_size_bytes
== 32 else 2 if key_size_bytes
== 24 else 0):
94 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
95 data
= data
[:expanded_key_size_bytes
]
100 def aes_encrypt(data
, expanded_key
):
102 Encrypt one block with aes
104 @param {int[]} data 16-Byte state
105 @param {int[]} expanded_key 176/208/240-Byte expanded key
106 @returns {int[]} 16-Byte cipher
108 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
110 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
111 for i
in range(1, rounds
+ 1):
112 data
= sub_bytes(data
)
113 data
= shift_rows(data
)
115 data
= mix_columns(data
)
116 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
121 def aes_decrypt(data
, expanded_key
):
123 Decrypt one block with aes
125 @param {int[]} data 16-Byte cipher
126 @param {int[]} expanded_key 176/208/240-Byte expanded key
127 @returns {int[]} 16-Byte state
129 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
131 for i
in range(rounds
, 0, -1):
132 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
134 data
= mix_columns_inv(data
)
135 data
= shift_rows_inv(data
)
136 data
= sub_bytes_inv(data
)
137 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
142 def aes_decrypt_text(data
, password
, key_size_bytes
):
145 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
146 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
147 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
148 - Mode of operation is 'counter'
150 @param {str} data Base64 encoded string
151 @param {str,unicode} password Password (will be encoded with utf-8)
152 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
153 @returns {str} Decrypted data
155 NONCE_LENGTH_BYTES
= 8
157 data
= bytes_to_intlist(base64
.b64decode(data
))
158 password
= bytes_to_intlist(password
.encode('utf-8'))
160 key
= password
[:key_size_bytes
] + [0] * (key_size_bytes
- len(password
))
161 key
= aes_encrypt(key
[:BLOCK_SIZE_BYTES
], key_expansion(key
)) * (key_size_bytes
// BLOCK_SIZE_BYTES
)
163 nonce
= data
[:NONCE_LENGTH_BYTES
]
164 cipher
= data
[NONCE_LENGTH_BYTES
:]
167 __value
= nonce
+ [0] * (BLOCK_SIZE_BYTES
- NONCE_LENGTH_BYTES
)
169 def next_value(self
):
171 self
.__value
= inc(self
.__value
)
174 decrypted_data
= aes_ctr_decrypt(cipher
, key
, Counter())
175 plaintext
= intlist_to_bytes(decrypted_data
)
179 RCON
= (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
180 SBOX
= (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
181 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
182 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
183 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
184 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
185 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
186 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
187 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
188 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
189 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
190 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
191 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
192 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
193 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
194 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
195 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
196 SBOX_INV
= (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
197 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
198 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
199 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
200 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
201 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
202 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
203 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
204 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
205 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
206 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
207 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
208 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
209 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
210 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
211 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
212 MIX_COLUMN_MATRIX
= ((0x2, 0x3, 0x1, 0x1),
213 (0x1, 0x2, 0x3, 0x1),
214 (0x1, 0x1, 0x2, 0x3),
215 (0x3, 0x1, 0x1, 0x2))
216 MIX_COLUMN_MATRIX_INV
= ((0xE, 0xB, 0xD, 0x9),
217 (0x9, 0xE, 0xB, 0xD),
218 (0xD, 0x9, 0xE, 0xB),
219 (0xB, 0xD, 0x9, 0xE))
220 RIJNDAEL_EXP_TABLE
= (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
221 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
222 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
223 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
224 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
225 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
226 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
227 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
228 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
229 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
230 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
231 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
232 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
233 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
234 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
235 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
236 RIJNDAEL_LOG_TABLE
= (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
237 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
238 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
239 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
240 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
241 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
242 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
243 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
244 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
245 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
246 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
247 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
248 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
249 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
250 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
251 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
255 return [SBOX
[x
] for x
in data
]
258 def sub_bytes_inv(data
):
259 return [SBOX_INV
[x
] for x
in data
]
263 return data
[1:] + [data
[0]]
266 def key_schedule_core(data
, rcon_iteration
):
268 data
= sub_bytes(data
)
269 data
[0] = data
[0] ^ RCON
[rcon_iteration
]
274 def xor(data1
, data2
):
275 return [x ^ y
for x
, y
in zip(data1
, data2
)]
278 def rijndael_mul(a
, b
):
279 if(a
== 0 or b
== 0):
281 return RIJNDAEL_EXP_TABLE
[(RIJNDAEL_LOG_TABLE
[a
] + RIJNDAEL_LOG_TABLE
[b
]) % 0xFF]
284 def mix_column(data
, matrix
):
288 for column
in range(4):
290 mixed ^
= rijndael_mul(data
[column
], matrix
[row
][column
])
291 data_mixed
.append(mixed
)
295 def mix_columns(data
, matrix
=MIX_COLUMN_MATRIX
):
298 column
= data
[i
* 4: (i
+ 1) * 4]
299 data_mixed
+= mix_column(column
, matrix
)
303 def mix_columns_inv(data
):
304 return mix_columns(data
, MIX_COLUMN_MATRIX_INV
)
307 def shift_rows(data
):
309 for column
in range(4):
311 data_shifted
.append(data
[((column
+ row
) & 0b11) * 4 + row
])
315 def shift_rows_inv(data
):
317 for column
in range(4):
319 data_shifted
.append(data
[((column
- row
) & 0b11) * 4 + row
])
324 data
= data
[:] # copy
325 for i
in range(len(data
) - 1, -1, -1):
329 data
[i
] = data
[i
] + 1