def parse_ike_proposal(proposal):
"""
Parse an IKE or ESP proposal string to extract encryption, hash, and DH group in human-readable format.
Args:
proposal (str): IKE or ESP proposal string, e.g., 'IKE:AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024',
'AES_GCM_16_256/PRF_HMAC_SHA2_256/ECP_384', or 'ESP:AES_CBC_256/HMAC_SHA1_96/NO_EXT_SEQ'
Returns:
dict: Dictionary with encryption, hash, and DH group in human-readable format
"""
dh_mapping = {
'MODP_768': '1',
'MODP_1024': '2',
'MODP_1536': '5',
'MODP_2048': '14',
'MODP_3072': '15',
'MODP_4096': '16',
'MODP_6144': '17',
'MODP_8192': '18',
'ECP_256': '19',
'ECP_384': '20',
'ECP_521': '21',
'ECP_192': '25',
'ECP_224': '26',
'MODP_1024_160': '22',
'MODP_2048_224': '23',
'MODP_2048_256': '24',
'FFDHE_2048': '256',
'FFDHE_3072': '257',
'FFDHE_4096': '258',
'FFDHE_6144': '259',
'FFDHE_8192': '260',
'ECP_224_BP': '27',
'ECP_256_BP': '28',
'ECP_384_BP': '29',
'ECP_512_BP': '30',
'CURVE_25519': '31',
'CURVE_448': '32',
}
enc_mapping = {
'AES_CBC_128': 'AES-128',
'AES_CBC_192': 'AES-192',
'AES_CBC_256': 'AES-256',
'AES_GCM_16_128': 'AES-GCM-128',
'AES_GCM_16_192': 'AES-GCM-192',
'AES_GCM_16_256': 'AES-GCM-256',
'AES_GCM_8_128': 'AES-GCM-128-8',
'AES_GCM_8_256': 'AES-GCM-256-8',
'AES_GCM_12_128': 'AES-GCM-128-12',
'AES_GCM_12_256': 'AES-GCM-256-12',
'AES_CCM_16_128': 'AES-CCM-128',
'AES_CCM_16_256': 'AES-CCM-256',
'AES_CTR_128': 'AES-CTR-128',
'AES_CTR_192': 'AES-CTR-192',
'AES_CTR_256': 'AES-CTR-256',
'3DES_CBC': '3DES',
'DES_CBC': 'DES',
'CAMELLIA_CBC_128': 'CAMELLIA-128',
'CAMELLIA_CBC_256': 'CAMELLIA-256',
'CHACHA20_POLY1305': 'CHACHA20-POLY1305',
'BLOWFISH_CBC': 'BLOWFISH',
'CAST5_CBC': 'CAST5',
'NULL': 'NULL'
}
hash_mapping = {
'HMAC_MD5': 'MD5',
'HMAC_MD5_96': 'MD5',
'HMAC_SHA1': 'SHA1',
'HMAC_SHA1_96': 'SHA1',
'HMAC_SHA2_256': 'SHA2-256',
'HMAC_SHA2_256_128': 'SHA2-256',
'HMAC_SHA2_384': 'SHA2-384',
'HMAC_SHA2_384_192': 'SHA2-384',
'HMAC_SHA2_512': 'SHA2-512',
'HMAC_SHA2_512_256': 'SHA2-512',
'HMAC_SHA3_224': 'SHA3-224',
'HMAC_SHA3_256': 'SHA3-256',
'HMAC_SHA3_384': 'SHA3-384',
'HMAC_SHA3_512': 'SHA3-512',
'AES_GMAC_128': 'GMAC-128',
'AES_GMAC_192': 'GMAC-192',
'AES_GMAC_256': 'GMAC-256',
'POLY1305': 'POLY1305',
'NONE': 'NULL'
}
components = proposal.split('/')
result = {
'encryption': "Unknown",
'hash': 'None',
'dh_group': 'None'
}
is_ike = proposal.startswith('IKE:')
is_esp = proposal.startswith('ESP:')
if is_ike or is_esp:
components[0] = components[0].replace('IKE:', '').replace('ESP:', '')
if len(components) == 4:
result['encryption'] = enc_mapping.get(components[0], 'Unknown')
result['hash'] = hash_mapping.get(components[1], 'Unknown')
result['dh_group'] = dh_mapping.get(components[3], 'None')
elif len(components) == 3:
result['encryption'] = enc_mapping.get(components[0], 'Unknown')
if (is_ike or not is_esp) and components[1].startswith('PRF_'):
result['hash'] = 'None'
result['dh_group'] = dh_mapping.get(components[2], 'None')
else:
result['hash'] = hash_mapping.get(components[1], 'Unknown')
result['dh_group'] = 'None'
if result['encryption'] == 'Unknown':
print(f"Unrecognized proposal: {proposal}")
return result
def process_proposals(proposal_list):
"""
Process a list of IKE or ESP proposals, concatenating encryption and hash values, and listing all unique DH groups.
Args:
proposal_list (str): Comma-separated string of IKE or ESP proposals
Returns:
str: Formatted string with concatenated encryption, hash, and DH groups
"""
proposal_list = proposal_list.replace(',', ', ')
proposals = proposal_list.strip().split(', ')
enc_set = set()
hash_set = set()
dh_set = set()
for proposal in proposals:
parsed = parse_ike_proposal(proposal.strip())
enc_set.add(parsed['encryption'])
if parsed['hash'] != 'None':
hash_set.add(parsed['hash'])
if parsed['dh_group'] != 'None':
dh_set.add(parsed['dh_group'])
enc_list = sorted(list(enc_set))
hash_list = sorted(list(hash_set))
dh_list = sorted(list(dh_set), key=lambda x: int(x))
enc_part = f"Encryption {' '.join(enc_list)}" if enc_list else "Encryption None"
hash_part = f" Hash {' '.join(hash_list)}" if hash_list else " Hash None"
dh_part = f" DH Group(s) {' '.join(dh_list)}" if dh_list else " DH Group(s) None"
return f"{enc_part}{hash_part}{dh_part}"
if __name__ == "__main__":
proposals = """IKE:AES_CBC_128/AES_CBC_256/HMAC_SHA1_96/HMAC_SHA2_256_128/HMAC_SHA2_384_192/HMAC_SHA2_512_256/PRF_HMAC_SHA1/PRF_HMAC_SHA2_256/PRF_HMAC_SHA2_384/PRF_HMAC_SHA2_512/MODP_1024/MODP_2048/MODP_3072/MODP_4096/MODP_6144/MODP_8192/ECP_256/ECP_384/ECP_521/MODP_1024_160/MODP_2048_224/MODP_2048_256, IKE:AES_GCM_16_128/AES_GCM_16_256/PRF_HMAC_SHA1/PRF_HMAC_SHA2_256/PRF_HMAC_SHA2_384/PRF_HMAC_SHA2_512/MODP_1024/MODP_2048/MODP_3072/MODP_4096/MODP_6144/MODP_8192/ECP_256/ECP_384/ECP_521/MODP_1024_160/MODP_2048_224/MODP_2048_256"""
print(process_proposals(proposals))