|  | @ -20,6 +20,8 @@ from __future__ import absolute_import, division, print_function, \ | 
			
		
	
		
		
			
				
					|  |  | from ctypes import c_char_p, c_int, c_ulong, c_ulonglong, byref, \ |  |  | from ctypes import c_char_p, c_int, c_ulong, c_ulonglong, byref, \ | 
			
		
	
		
		
			
				
					|  |  |     create_string_buffer, c_void_p |  |  |     create_string_buffer, c_void_p | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | import logging | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | from shadowsocks.crypto import util |  |  | from shadowsocks.crypto import util | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | __all__ = ['ciphers'] |  |  | __all__ = ['ciphers'] | 
			
		
	
	
		
		
			
				
					|  | @ -59,6 +61,27 @@ def load_libsodium(): | 
			
		
	
		
		
			
				
					|  |  |                                                                  c_char_p, c_ulong, |  |  |                                                                  c_char_p, c_ulong, | 
			
		
	
		
		
			
				
					|  |  |                                                                  c_char_p) |  |  |                                                                  c_char_p) | 
			
		
	
		
		
			
				
					|  |  |     except: |  |  |     except: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         logging.info("ChaCha20 IETF not support.") | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         pass | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     try: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         libsodium.crypto_stream_xsalsa20_xor_ic.restype = c_int | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         libsodium.crypto_stream_xsalsa20_xor_ic.argtypes = (c_void_p, c_char_p, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                             c_ulonglong, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                             c_char_p, c_ulonglong, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                             c_char_p) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     except: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         logging.info("XSalsa20 not support.") | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         pass | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     try: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         libsodium.crypto_stream_xchacha20_xor_ic.restype = c_int | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         libsodium.crypto_stream_xchacha20_xor_ic.argtypes = (c_void_p, c_char_p, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                              c_ulonglong, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                              c_char_p, c_ulonglong, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                                              c_char_p) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     except: | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         logging.info("XChaCha20 not support. XChaCha20 only support since libsodium v1.0.12") | 
			
		
	
		
		
			
				
					|  |  |         pass |  |  |         pass | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     buf = create_string_buffer(buf_size) |  |  |     buf = create_string_buffer(buf_size) | 
			
		
	
	
		
		
			
				
					|  | @ -79,6 +102,10 @@ class SodiumCrypto(object): | 
			
		
	
		
		
			
				
					|  |  |             self.cipher = libsodium.crypto_stream_chacha20_xor_ic |  |  |             self.cipher = libsodium.crypto_stream_chacha20_xor_ic | 
			
		
	
		
		
			
				
					|  |  |         elif cipher_name == 'chacha20-ietf': |  |  |         elif cipher_name == 'chacha20-ietf': | 
			
		
	
		
		
			
				
					|  |  |             self.cipher = libsodium.crypto_stream_chacha20_ietf_xor_ic |  |  |             self.cipher = libsodium.crypto_stream_chacha20_ietf_xor_ic | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         elif cipher_name == 'xchacha20': | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.cipher = libsodium.crypto_stream_xchacha20_xor_ic | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         elif cipher_name == 'xsalsa20': | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             self.cipher = libsodium.crypto_stream_xsalsa20_xor_ic | 
			
		
	
		
		
			
				
					|  |  |         else: |  |  |         else: | 
			
		
	
		
		
			
				
					|  |  |             raise Exception('Unknown cipher') |  |  |             raise Exception('Unknown cipher') | 
			
		
	
		
		
			
				
					|  |  |         # byte counter, not block counter |  |  |         # byte counter, not block counter | 
			
		
	
	
		
		
			
				
					|  | @ -107,10 +134,13 @@ class SodiumCrypto(object): | 
			
		
	
		
		
			
				
					|  |  |     def clean(self): |  |  |     def clean(self): | 
			
		
	
		
		
			
				
					|  |  |         pass |  |  |         pass | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | ciphers = { |  |  | ciphers = { | 
			
		
	
		
		
			
				
					|  |  |     'salsa20': (32, 8, SodiumCrypto), |  |  |     'salsa20': (32, 8, SodiumCrypto), | 
			
		
	
		
		
			
				
					|  |  |     'chacha20': (32, 8, SodiumCrypto), |  |  |     'chacha20': (32, 8, SodiumCrypto), | 
			
		
	
		
		
			
				
					|  |  |     'chacha20-ietf': (32, 12, SodiumCrypto), |  |  |     'chacha20-ietf': (32, 12, SodiumCrypto), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     'xchacha20': (32, 24, SodiumCrypto), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     'xsalsa20': (32, 24, SodiumCrypto), | 
			
		
	
		
		
			
				
					|  |  | } |  |  | } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -122,7 +152,6 @@ def test_salsa20(): | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | def test_chacha20(): |  |  | def test_chacha20(): | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     cipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 1) |  |  |     cipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 1) | 
			
		
	
		
		
			
				
					|  |  |     decipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 0) |  |  |     decipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 0) | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -130,13 +159,29 @@ def test_chacha20(): | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | def test_chacha20_ietf(): |  |  | def test_chacha20_ietf(): | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     cipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 1) |  |  |     cipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 1) | 
			
		
	
		
		
			
				
					|  |  |     decipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 0) |  |  |     decipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 0) | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     util.run_cipher(cipher, decipher) |  |  |     util.run_cipher(cipher, decipher) | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | def test_xchacha20(): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     cipher = SodiumCrypto('xchacha20', b'k' * 32, b'i' * 24, 1) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     decipher = SodiumCrypto('xchacha20', b'k' * 32, b'i' * 24, 0) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     util.run_cipher(cipher, decipher) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | def test_xsalsa20(): | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     cipher = SodiumCrypto('xsalsa20', b'k' * 32, b'i' * 24, 1) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     decipher = SodiumCrypto('xsalsa20', b'k' * 32, b'i' * 24, 0) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     util.run_cipher(cipher, decipher) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | if __name__ == '__main__': |  |  | if __name__ == '__main__': | 
			
		
	
		
		
			
				
					|  |  |     test_chacha20_ietf() |  |  |     test_chacha20_ietf() | 
			
		
	
		
		
			
				
					|  |  |     test_chacha20() |  |  |     test_chacha20() | 
			
		
	
		
		
			
				
					|  |  |     test_salsa20() |  |  |     test_salsa20() | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     test_xchacha20() | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     test_xsalsa20() | 
			
		
	
	
		
		
			
				
					|  | 
 |