2015-08-05 18:36:39 +00:00
|
|
|
"""
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
Empire encryption functions.
|
|
|
|
|
|
|
|
Includes:
|
|
|
|
|
|
|
|
pad() - performs PKCS#7 padding
|
|
|
|
depad() - Performs PKCS#7 depadding
|
|
|
|
rsa_xml_to_key() - parses a PowerShell RSA xml import and builds a M2Crypto object
|
|
|
|
rsa_encrypt() - encrypts data using the M2Crypto crypto object
|
|
|
|
aes_encrypt() - encrypts data using a pyCrypto AES object
|
|
|
|
aes_encrypt_then_hmac() - encrypts and SHA256 HMACs data using a pyCrypto AES object
|
|
|
|
aes_decrypt() - decrypts data using a pyCrypto AES object
|
|
|
|
verify_hmac() - verifies a SHA256 HMAC for a data blob
|
|
|
|
aes_decrypt_and_verify() - AES decrypts data if the HMAC is validated
|
|
|
|
generate_aes_key() - generates a ranodm AES key using pyCrypto's Random functionality
|
|
|
|
rc4() - encrypt/decrypt a data blob using an RC4 key
|
|
|
|
DiffieHellman() - Mark Loiseau's DiffieHellman implementation, see ./data/licenses/ for license info
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
import base64
|
|
|
|
import hashlib
|
|
|
|
import hmac
|
|
|
|
import string
|
|
|
|
import M2Crypto
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
from xml.dom.minidom import parseString
|
|
|
|
from Crypto.Cipher import AES
|
|
|
|
from Crypto import Random
|
|
|
|
from Crypto.Random import random
|
2016-09-23 18:04:35 +00:00
|
|
|
from binascii import hexlify
|
|
|
|
|
|
|
|
|
|
|
|
def to_bufferable(binary):
|
|
|
|
return binary
|
|
|
|
|
|
|
|
def _get_byte(c):
|
|
|
|
return ord(c)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
# Python 3 compatibility stuffz
|
|
|
|
try:
|
|
|
|
xrange
|
|
|
|
except Exception:
|
|
|
|
xrange = range
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
def to_bufferable(binary):
|
|
|
|
if isinstance(binary, bytes):
|
|
|
|
return binary
|
|
|
|
return bytes(ord(b) for b in binary)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
def _get_byte(c):
|
|
|
|
return c
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
# If a secure random number generator is unavailable, exit with an error.
|
|
|
|
try:
|
|
|
|
import ssl
|
|
|
|
random_function = ssl.RAND_bytes
|
|
|
|
random_provider = "Python SSL"
|
|
|
|
except (AttributeError, ImportError):
|
|
|
|
import OpenSSL
|
|
|
|
random_function = OpenSSL.rand.bytes
|
|
|
|
random_provider = "OpenSSL"
|
|
|
|
|
|
|
|
|
|
|
|
def pad(data):
|
2015-08-05 18:36:39 +00:00
|
|
|
"""
|
|
|
|
Performs PKCS#7 padding for 128 bit block size.
|
|
|
|
"""
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
if (len(data) % 16) == 0:
|
|
|
|
return data
|
|
|
|
else:
|
|
|
|
pad = 16 - (len(data) % 16)
|
|
|
|
return data + to_bufferable(chr(pad) * pad)
|
|
|
|
|
|
|
|
# return str(s) + chr(16 - len(str(s)) % 16) * (16 - len(str(s)) % 16)
|
2015-08-05 18:36:39 +00:00
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
|
|
|
|
def depad(data):
|
2015-08-05 18:36:39 +00:00
|
|
|
"""
|
|
|
|
Performs PKCS#7 depadding for 128 bit block size.
|
|
|
|
"""
|
2016-09-23 18:04:35 +00:00
|
|
|
if len(data) % 16 != 0:
|
|
|
|
raise ValueError("invalid length")
|
|
|
|
|
|
|
|
pad = _get_byte(data[-1])
|
|
|
|
|
|
|
|
if pad <= 16:
|
|
|
|
return data[:-pad]
|
|
|
|
else:
|
|
|
|
return data
|
|
|
|
|
|
|
|
# return s[:-(ord(s[-1]))]
|
2015-08-05 18:36:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
def rsa_xml_to_key(xml):
|
|
|
|
"""
|
|
|
|
Parse powershell RSA.ToXmlString() public key string and
|
|
|
|
return a M2Crypto key object.
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
Used during PowerShell RSA-EKE key exchange in agents.py.
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
Reference- http://stackoverflow.com/questions/10367072/m2crypto-import-keys-from-non-standard-file
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
# parse the xml DOM and extract the exponent/modulus
|
|
|
|
dom = parseString(xml)
|
|
|
|
e = base64.b64decode(dom.getElementsByTagName('Exponent')[0].childNodes[0].data)
|
|
|
|
n = base64.b64decode(dom.getElementsByTagName('Modulus')[0].childNodes[0].data)
|
|
|
|
|
|
|
|
# build the new key
|
|
|
|
key = M2Crypto.RSA.new_pub_key((
|
|
|
|
M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hexlify(e))),
|
|
|
|
M2Crypto.m2.bn_to_mpi(M2Crypto.m2.hex_to_bn(hexlify(n))),
|
|
|
|
))
|
|
|
|
|
|
|
|
return key
|
|
|
|
# if there's an XML parsing error, return None
|
|
|
|
except:
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def rsa_encrypt(key, data):
|
|
|
|
"""
|
|
|
|
Take a M2Crypto key object and use it to encrypt the passed data.
|
|
|
|
"""
|
|
|
|
return key.public_encrypt(data, M2Crypto.RSA.pkcs1_padding)
|
|
|
|
|
|
|
|
|
|
|
|
def aes_encrypt(key, data):
|
|
|
|
"""
|
|
|
|
Generate a random IV and new AES cipher object with the given
|
|
|
|
key, and return IV + encryptedData.
|
|
|
|
"""
|
|
|
|
IV = Random.new().read(16)
|
|
|
|
cipher = AES.new(key, AES.MODE_CBC, IV)
|
|
|
|
return IV + cipher.encrypt(pad(data))
|
|
|
|
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
def aes_encrypt_then_hmac(key, data):
|
2015-08-08 17:51:27 +00:00
|
|
|
"""
|
|
|
|
Encrypt the data then calculate HMAC over the ciphertext.
|
|
|
|
"""
|
|
|
|
data = aes_encrypt(key, data)
|
2016-09-23 18:04:35 +00:00
|
|
|
mac = hmac.new(str(key), data, hashlib.sha256).digest()
|
|
|
|
return data + mac[0:10]
|
2015-08-08 17:51:27 +00:00
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def aes_decrypt(key, data):
|
|
|
|
"""
|
|
|
|
Generate an AES cipher object, pull out the IV from the data
|
|
|
|
and return the unencrypted data.
|
|
|
|
"""
|
|
|
|
if len(data) > 16:
|
|
|
|
IV = data[0:16]
|
|
|
|
cipher = AES.new(key, AES.MODE_CBC, IV)
|
|
|
|
return depad(cipher.decrypt(data[16:]))
|
|
|
|
|
|
|
|
|
2015-08-08 17:51:27 +00:00
|
|
|
def verify_hmac(key, data):
|
|
|
|
"""
|
|
|
|
Verify the HMAC supplied in the data with the given key.
|
|
|
|
"""
|
2015-08-27 22:40:19 +00:00
|
|
|
if len(data) > 20:
|
2016-09-23 18:04:35 +00:00
|
|
|
mac = data[-10:]
|
|
|
|
data = data[:-10]
|
|
|
|
expected = hmac.new(key, data, hashlib.sha256).digest()[0:10]
|
2015-08-08 17:51:27 +00:00
|
|
|
# Double HMAC to prevent timing attacks. hmac.compare_digest() is
|
|
|
|
# preferable, but only available since Python 2.7.7.
|
|
|
|
return hmac.new(str(key), expected).digest() == hmac.new(str(key), mac).digest()
|
2016-09-23 18:04:35 +00:00
|
|
|
else:
|
|
|
|
return False
|
2015-08-08 17:51:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
def aes_decrypt_and_verify(key, data):
|
|
|
|
"""
|
|
|
|
Decrypt the data, but only if it has a valid MAC.
|
|
|
|
"""
|
|
|
|
if len(data) > 32 and verify_hmac(key, data):
|
2016-09-23 18:04:35 +00:00
|
|
|
return aes_decrypt(key, data[:-10])
|
2015-08-08 17:51:27 +00:00
|
|
|
raise Exception("Invalid ciphertext received.")
|
|
|
|
|
|
|
|
|
2015-08-05 18:36:39 +00:00
|
|
|
def generate_aes_key():
|
|
|
|
"""
|
|
|
|
Generate a random new 128-bit AES key using Pycrypto's secure Random functions.
|
|
|
|
"""
|
|
|
|
punctuation = '!#$%&()*+,-./:;<=>?@[\]^_`{|}~'
|
|
|
|
return ''.join(random.sample(string.ascii_letters + string.digits + '!#$%&()*+,-./:;<=>?@[\]^_`{|}~', 32))
|
|
|
|
|
|
|
|
|
2016-09-23 18:04:35 +00:00
|
|
|
def rc4(key, data):
|
2015-08-05 18:36:39 +00:00
|
|
|
"""
|
2016-09-23 18:04:35 +00:00
|
|
|
RC4 encrypt/decrypt the given data input with the specified key.
|
|
|
|
|
|
|
|
From: http://stackoverflow.com/questions/29607753/how-to-decrypt-a-file-that-encrypted-with-rc4-using-python
|
2015-08-05 18:36:39 +00:00
|
|
|
"""
|
2016-09-23 18:04:35 +00:00
|
|
|
|
|
|
|
S, j, out = range(256), 0, []
|
|
|
|
|
|
|
|
# KSA Phase
|
|
|
|
for i in range(256):
|
|
|
|
j = (j + S[i] + ord(key[i % len(key)])) % 256
|
|
|
|
S[i], S[j] = S[j], S[i]
|
|
|
|
|
|
|
|
# PRGA Phase
|
|
|
|
i = j = 0
|
|
|
|
for char in data:
|
|
|
|
i = (i + 1) % 256
|
|
|
|
j = (j + S[i]) % 256
|
|
|
|
S[i], S[j] = S[j], S[i]
|
|
|
|
out.append(chr(ord(char) ^ S[(S[i] + S[j]) % 256]))
|
|
|
|
|
|
|
|
return ''.join(out)
|
|
|
|
|
|
|
|
|
|
|
|
class DiffieHellman(object):
|
|
|
|
"""
|
|
|
|
A reference implementation of the Diffie-Hellman protocol.
|
|
|
|
By default, this class uses the 6144-bit MODP Group (Group 17) from RFC 3526.
|
|
|
|
This prime is sufficient to generate an AES 256 key when used with
|
|
|
|
a 540+ bit exponent.
|
|
|
|
|
|
|
|
Authored by Mark Loiseau's implementation at https://github.com/lowazo/pyDHE
|
|
|
|
version 3.0 of the GNU General Public License
|
|
|
|
see ./data/licenses/pyDHE_license.txt for license info
|
|
|
|
|
|
|
|
Also used in ./data/agent/stager.py for the Python key-negotiation stager
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, generator=2, group=17, keyLength=540):
|
|
|
|
"""
|
|
|
|
Generate the public and private keys.
|
|
|
|
"""
|
|
|
|
min_keyLength = 180
|
|
|
|
|
|
|
|
default_generator = 2
|
|
|
|
valid_generators = [2, 3, 5, 7]
|
|
|
|
|
|
|
|
# Sanity check fors generator and keyLength
|
|
|
|
if(generator not in valid_generators):
|
|
|
|
print("Error: Invalid generator. Using default.")
|
|
|
|
self.generator = default_generator
|
|
|
|
else:
|
|
|
|
self.generator = generator
|
|
|
|
|
|
|
|
if(keyLength < min_keyLength):
|
|
|
|
print("Error: keyLength is too small. Setting to minimum.")
|
|
|
|
self.keyLength = min_keyLength
|
|
|
|
else:
|
|
|
|
self.keyLength = keyLength
|
|
|
|
|
|
|
|
self.prime = self.getPrime(group)
|
|
|
|
|
|
|
|
self.privateKey = self.genPrivateKey(keyLength)
|
|
|
|
self.publicKey = self.genPublicKey()
|
|
|
|
|
|
|
|
def getPrime(self, group=17):
|
|
|
|
"""
|
|
|
|
Given a group number, return a prime.
|
|
|
|
"""
|
|
|
|
default_group = 17
|
|
|
|
|
|
|
|
primes = {
|
|
|
|
5: 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF,
|
|
|
|
14: 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF,
|
|
|
|
15: 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF,
|
|
|
|
16: 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF,
|
|
|
|
17:
|
|
|
|
0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF,
|
|
|
|
18:
|
|
|
|
0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF
|
|
|
|
}
|
|
|
|
|
|
|
|
if group in primes.keys():
|
|
|
|
return primes[group]
|
|
|
|
else:
|
|
|
|
print("Error: No prime with group %i. Using default." % group)
|
|
|
|
return primes[default_group]
|
|
|
|
|
|
|
|
def genRandom(self, bits):
|
|
|
|
"""
|
|
|
|
Generate a random number with the specified number of bits
|
|
|
|
"""
|
|
|
|
_rand = 0
|
|
|
|
_bytes = bits // 8 + 8
|
|
|
|
|
|
|
|
while(len(bin(_rand))-2 < bits):
|
|
|
|
try:
|
|
|
|
# Python 3
|
|
|
|
_rand = int.from_bytes(random_function(_bytes), byteorder='big')
|
|
|
|
except:
|
|
|
|
# Python 2
|
|
|
|
_rand = int(OpenSSL.rand.bytes(_bytes).encode('hex'), 16)
|
|
|
|
|
|
|
|
return _rand
|
|
|
|
|
|
|
|
def genPrivateKey(self, bits):
|
|
|
|
"""
|
|
|
|
Generate a private key using a secure random number generator.
|
|
|
|
"""
|
|
|
|
return self.genRandom(bits)
|
|
|
|
|
|
|
|
def genPublicKey(self):
|
|
|
|
"""
|
|
|
|
Generate a public key X with g**x % p.
|
|
|
|
"""
|
|
|
|
return pow(self.generator, self.privateKey, self.prime)
|
|
|
|
|
|
|
|
def checkPublicKey(self, otherKey):
|
|
|
|
"""
|
|
|
|
Check the other party's public key to make sure it's valid.
|
|
|
|
Since a safe prime is used, verify that the Legendre symbol == 1
|
|
|
|
"""
|
|
|
|
if(otherKey > 2 and otherKey < self.prime - 1):
|
|
|
|
if(pow(otherKey, (self.prime - 1)//2, self.prime) == 1):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def genSecret(self, privateKey, otherKey):
|
|
|
|
"""
|
|
|
|
Check to make sure the public key is valid, then combine it with the
|
|
|
|
private key to generate a shared secret.
|
|
|
|
"""
|
|
|
|
if(self.checkPublicKey(otherKey) is True):
|
|
|
|
sharedSecret = pow(otherKey, privateKey, self.prime)
|
|
|
|
return sharedSecret
|
|
|
|
else:
|
|
|
|
raise Exception("Invalid public key.")
|
|
|
|
|
|
|
|
def genKey(self, otherKey):
|
|
|
|
"""
|
|
|
|
Derive the shared secret, then hash it to obtain the shared key.
|
|
|
|
"""
|
|
|
|
self.sharedSecret = self.genSecret(self.privateKey, otherKey)
|
|
|
|
|
|
|
|
# Convert the shared secret (int) to an array of bytes in network order
|
|
|
|
# Otherwise hashlib can't hash it.
|
|
|
|
try:
|
|
|
|
_sharedSecretBytes = self.sharedSecret.to_bytes(
|
|
|
|
len(bin(self.sharedSecret))-2 // 8 + 1, byteorder="big")
|
|
|
|
except AttributeError:
|
|
|
|
_sharedSecretBytes = str(self.sharedSecret)
|
|
|
|
|
|
|
|
s = hashlib.sha256()
|
|
|
|
s.update(bytes(_sharedSecretBytes))
|
|
|
|
self.key = s.digest()
|
|
|
|
|
|
|
|
def getKey(self):
|
|
|
|
"""
|
|
|
|
Return the shared secret key
|
|
|
|
"""
|
|
|
|
return self.key
|
|
|
|
|