diff --git a/mapper/ciphersuites.json b/mapper/ciphersuites.json index 44542d946..9f4583301 100644 --- a/mapper/ciphersuites.json +++ b/mapper/ciphersuites.json @@ -1 +1 @@ -{"ciphersuites": [{"TLS_AES_128_CCM_8_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x13", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "TLS_AES_128_CCM_SHA256", "hex_byte_1": "0x13", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "TLS_AES_128_GCM_SHA256", "hex_byte_1": "0x13", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "TLS_AES_256_GCM_SHA384", "hex_byte_1": "0x13", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_CHACHA20_POLY1305_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x13", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x19", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x17", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_3DES_EDE_CBC_SHA1", "openssl_name": "ADH-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x1B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_AES_128_CBC_SHA1", "openssl_name": "ADH-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x34", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_128_CBC_SHA256", "openssl_name": "ADH-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6C", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_128_GCM_SHA256", "openssl_name": "ADH-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA6", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_AES_256_CBC_SHA1", "openssl_name": "ADH-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x3A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_256_CBC_SHA256", "openssl_name": "ADH-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6D", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DH_ANON_AES_256_GCM_SHA384", "openssl_name": "ADH-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA7", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x46", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x47", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_CBC_SHA1", "openssl_name": "ADH-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x46", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_CBC_SHA256", "openssl_name": "ADH-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBF", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x84", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_CBC_SHA1", "openssl_name": "ADH-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x89", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_CBC_SHA256", "openssl_name": "ADH-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC5", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x85", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_RC4_128_MD5": {"gnutls_name": "TLS_DH_ANON_ARCFOUR_128_MD5", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x18", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "ADH-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x9B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0B", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0D", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x30", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x3E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA4", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x36", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x68", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA5", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x58", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x59", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x42", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xBB", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x82", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x85", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC1", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x83", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0C", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x97", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x11", "protocol_version": "TLS EXPORT", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-DSS-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x13", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_AES_128_CBC_SHA1", "openssl_name": "DHE-DSS-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x32", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_128_CBC_SHA256", "openssl_name": "DHE-DSS-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x40", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_128_GCM_SHA256", "openssl_name": "DHE-DSS-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_AES_256_CBC_SHA1", "openssl_name": "DHE-DSS-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x38", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_256_CBC_SHA256", "openssl_name": "DHE-DSS-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6A", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_DSS_AES_256_GCM_SHA384", "openssl_name": "DHE-DSS-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x42", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x56", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x43", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x57", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA1", "openssl_name": "DHE-DSS-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x44", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-DSS-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBD", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x80", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA1", "openssl_name": "DHE-DSS-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x87", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA256", "openssl_name": "DHE-DSS-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x81", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x12", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "DHE-DSS-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x99", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_AES_128_CBC_SHA1", "openssl_name": "DHE-PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x90", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_PSK_AES_128_CBC_SHA256", "openssl_name": "DHE-PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CCM": {"gnutls_name": "TLS_DHE_PSK_AES_128_CCM", "openssl_name": "DHE-PSK-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA6", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_PSK_AES_128_GCM_SHA256", "openssl_name": "DHE-PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_AES_256_CBC_SHA1", "openssl_name": "DHE-PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x91", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_DHE_PSK_AES_256_CBC_SHA384", "openssl_name": "DHE-PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CCM": {"gnutls_name": "TLS_DHE_PSK_AES_256_CCM", "openssl_name": "DHE-PSK-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA7", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_PSK_AES_256_GCM_SHA384", "openssl_name": "DHE-PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x66", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6C", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x67", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x96", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x90", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "DHE-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x97", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x91", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_DHE_PSK_CHACHA20_POLY1305", "openssl_name": "DHE-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA1", "openssl_name": "DHE-PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA256", "openssl_name": "DHE-PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB4", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA384", "openssl_name": "DHE-PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB5", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_DHE_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x8E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x14", "protocol_version": "TLS EXPORT", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-RSA-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x16", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_AES_128_CBC_SHA1", "openssl_name": "DHE-RSA-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x33", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_128_CBC_SHA256", "openssl_name": "DHE-RSA-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x67", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_DHE_RSA_AES_128_CCM", "openssl_name": "DHE-RSA-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_DHE_RSA_AES_128_CCM_8", "openssl_name": "DHE-RSA-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_128_GCM_SHA256", "openssl_name": "DHE-RSA-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x9E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_AES_256_CBC_SHA1", "openssl_name": "DHE-RSA-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x39", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_256_CBC_SHA256", "openssl_name": "DHE-RSA-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6B", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_DHE_RSA_AES_256_CCM", "openssl_name": "DHE-RSA-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_DHE_RSA_AES_256_CCM_8", "openssl_name": "DHE-RSA-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_RSA_AES_256_GCM_SHA384", "openssl_name": "DHE-RSA-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0x9F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x44", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x52", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x45", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x53", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA1", "openssl_name": "DHE-RSA-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x45", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-RSA-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBE", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7C", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1", "openssl_name": "DHE-RSA-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x88", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA256", "openssl_name": "DHE-RSA-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC4", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_DHE_RSA_CHACHA20_POLY1305", "openssl_name": "DHE-RSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x15", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "DHE-RSA-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x9A", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0E", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x10", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x31", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x3F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA0", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x37", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x69", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA1", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x40", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x54", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x41", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x55", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x43", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xBC", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x86", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC2", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x98", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB2", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB0", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_256_CCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB3", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB1", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_3DES_EDE_CBC_SHA1", "openssl_name": "AECDH-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x17", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_AES_128_CBC_SHA1", "openssl_name": "AECDH-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x18", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_AES_256_CBC_SHA1", "openssl_name": "AECDH-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x19", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDH_ANON_NULL_SHA1", "openssl_name": "AECDH-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x15", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDH_ANON_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x16", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x25", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x26", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4A", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4B", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x74", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x88", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x75", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x89", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_NULL_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x08", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x09", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CBC_SHA256", "openssl_name": "ECDHE-ECDSA-AES128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x23", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CCM", "openssl_name": "ECDHE-ECDSA-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CCM_8", "openssl_name": "ECDHE-ECDSA-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_GCM_SHA256", "openssl_name": "ECDHE-ECDSA-AES128-GCM-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x2B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x0A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CBC_SHA384", "openssl_name": "ECDHE-ECDSA-AES256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x24", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CCM", "openssl_name": "ECDHE-ECDSA-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CCM_8", "openssl_name": "ECDHE-ECDSA-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAF", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_GCM_SHA384", "openssl_name": "ECDHE-ECDSA-AES256-GCM-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x2C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x48", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x49", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5D", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-ECDSA-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x72", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x86", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-ECDSA-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x73", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x87", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CHACHA20_POLY1305", "openssl_name": "ECDHE-ECDSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_NULL_SHA1", "openssl_name": "ECDHE-ECDSA-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x06", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x07", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x34", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_AES_128_CBC_SHA1", "openssl_name": "ECDHE-PSK-AES128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x35", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_AES_128_CBC_SHA256", "openssl_name": "ECDHE-PSK-AES128-CBC-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x37", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_AES_256_CBC_SHA1", "openssl_name": "ECDHE-PSK-AES256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x36", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_AES_256_CBC_SHA384", "openssl_name": "ECDHE-PSK-AES256-CBC-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x38", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x70", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x71", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x9A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x9B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_CHACHA20_POLY1305", "openssl_name": "ECDHE-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA1", "openssl_name": "ECDHE-PSK-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x39", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA256", "openssl_name": "ECDHE-PSK-NULL-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x3A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA384", "openssl_name": "ECDHE-PSK-NULL-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x3B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x33", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-RSA-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x12", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_CBC_SHA1", "openssl_name": "ECDHE-RSA-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x13", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_CBC_SHA256", "openssl_name": "ECDHE-RSA-AES128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x27", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_GCM_SHA256", "openssl_name": "ECDHE-RSA-AES128-GCM-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x2F", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_CBC_SHA1", "openssl_name": "ECDHE-RSA-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x14", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_CBC_SHA384", "openssl_name": "ECDHE-RSA-AES256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x28", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_GCM_SHA384", "openssl_name": "ECDHE-RSA-AES256-GCM-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x30", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x60", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4D", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x61", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-RSA-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x76", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-RSA-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x77", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CHACHA20_POLY1305", "openssl_name": "ECDHE-RSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_RSA_NULL_SHA1", "openssl_name": "ECDHE-RSA-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x10", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_RSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x11", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x29", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x31", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2A", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x32", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x62", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x63", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x78", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8C", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x79", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_NULL_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0B", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0C", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_28147_CNT_IMIT": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "28147 CNT", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x00", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "KUZNYECHIK CTR", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "KUZNYECHIK MGM L", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "KUZNYECHIK MGM S", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "MAGMA CTR", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_MGM_L": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "MAGMA MGM L", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_MGM_S": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x06", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "MAGMA MGM S", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x29", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x26", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x2A", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x27", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x2B", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC4_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x28", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_3DES_EDE_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x23", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1F", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_DES_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x22", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1E", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_IDEA_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x25", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "IDEA CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_IDEA_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x21", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "IDEA CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_RC4_128_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x24", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x20", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_NULL_WITH_NULL_NULL": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x00", "protocol_version": "TLS", "kex_algorithm": "NULL", "auth_algorithm": "NULL", "enc_algorithm": "NULL", "hash_algorithm": "NULL", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_DHE_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_DHE_PSK_AES_128_CCM_8", "openssl_name": "DHE-PSK-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_DHE_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_DHE_PSK_AES_256_CCM_8", "openssl_name": "DHE-PSK-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8B", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_PSK_AES_128_CBC_SHA1", "openssl_name": "PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8C", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_PSK_AES_128_CBC_SHA256", "openssl_name": "PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CCM": {"gnutls_name": "TLS_PSK_AES_128_CCM", "openssl_name": "PSK-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA4", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_PSK_AES_128_CCM_8", "openssl_name": "PSK-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_PSK_AES_128_GCM_SHA256", "openssl_name": "PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_PSK_AES_256_CBC_SHA1", "openssl_name": "PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8D", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_PSK_AES_256_CBC_SHA384", "openssl_name": "PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAF", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CCM": {"gnutls_name": "TLS_PSK_AES_256_CCM", "openssl_name": "PSK-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA5", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_PSK_AES_256_CCM_8", "openssl_name": "PSK-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_PSK_AES_256_GCM_SHA384", "openssl_name": "PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x64", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6A", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x65", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6B", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x94", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8E", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x95", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8F", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_PSK_CHACHA20_POLY1305", "openssl_name": "PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_PSK_NULL_SHA1", "openssl_name": "PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2C", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_PSK_NULL_SHA256", "openssl_name": "PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB0", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_PSK_NULL_SHA384", "openssl_name": "PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB1", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x8A", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x08", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x06", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x03", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "RSA-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x93", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_AES_128_CBC_SHA1", "openssl_name": "RSA-PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x94", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_PSK_AES_128_CBC_SHA256", "openssl_name": "RSA-PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB6", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_PSK_AES_128_GCM_SHA256", "openssl_name": "RSA-PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_AES_256_CBC_SHA1", "openssl_name": "RSA-PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x95", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_RSA_PSK_AES_256_CBC_SHA384", "openssl_name": "RSA-PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB7", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_PSK_AES_256_GCM_SHA384", "openssl_name": "RSA-PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x68", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6E", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x69", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6F", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "RSA-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x98", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x92", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "RSA-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x99", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x93", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_RSA_PSK_CHACHA20_POLY1305", "openssl_name": "RSA-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA1", "openssl_name": "RSA-PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2E", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA256", "openssl_name": "RSA-PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB8", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA384", "openssl_name": "RSA-PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB9", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_RSA_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x92", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x0A", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_RSA_AES_128_CBC_SHA1", "openssl_name": "AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2F", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_AES_128_CBC_SHA256", "openssl_name": "AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_RSA_AES_128_CCM", "openssl_name": "AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_RSA_AES_128_CCM_8", "openssl_name": "AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA0", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_AES_128_GCM_SHA256", "openssl_name": "AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x9C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_RSA_AES_256_CBC_SHA1", "openssl_name": "AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x35", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_RSA_AES_256_CBC_SHA256", "openssl_name": "AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_RSA_AES_256_CCM", "openssl_name": "AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_RSA_AES_256_CCM_8", "openssl_name": "AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA1", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_AES_256_GCM_SHA384", "openssl_name": "AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0x9D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x50", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x51", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_RSA_CAMELLIA_128_CBC_SHA1", "openssl_name": "CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x41", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBA", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7A", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_RSA_CAMELLIA_256_CBC_SHA1", "openssl_name": "CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x84", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_256_CBC_SHA256", "openssl_name": "CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC0", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7B", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x09", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_IDEA_CBC_SHA": {"gnutls_name": "", "openssl_name": "IDEA-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x07", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "IDEA CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_MD5": {"gnutls_name": "TLS_RSA_NULL_MD5", "openssl_name": "NULL-MD5", "hex_byte_1": "0x00", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_SHA": {"gnutls_name": "TLS_RSA_NULL_SHA1", "openssl_name": "NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_SHA256": {"gnutls_name": "TLS_RSA_NULL_SHA256", "openssl_name": "NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3B", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_RC4_128_MD5": {"gnutls_name": "TLS_RSA_ARCFOUR_128_MD5", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_RSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x96", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SHA256_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB4", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "SHA256", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SHA384_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB5", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "SHA384", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SM4_CCM_SM3": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC7", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "SM4 CCM", "hash_algorithm": "SM3", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SM4_GCM_SM3": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC6", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "SM4 GCM", "hash_algorithm": "SM3", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-DSS-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1C", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_AES_128_CBC_SHA1", "openssl_name": "SRP-DSS-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1F", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_AES_256_CBC_SHA1", "openssl_name": "SRP-DSS-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x22", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-RSA-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1B", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_AES_128_CBC_SHA1", "openssl_name": "SRP-RSA-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1E", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_AES_256_CBC_SHA1", "openssl_name": "SRP-RSA-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x21", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1A", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_AES_128_CBC_SHA1", "openssl_name": "SRP-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1D", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_AES_256_CBC_SHA1", "openssl_name": "SRP-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x20", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}]} \ No newline at end of file +{"ciphersuites": [{"TLS_AES_128_CCM_8_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x13", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_CCM_ASCONHASH256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x71", "protocol_version": "TLS", "kex_algorithm": "AES", "auth_algorithm": "128 CCM ASCONHASH256", "enc_algorithm": "", "hash_algorithm": "", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "TLS_AES_128_CCM_SHA256", "hex_byte_1": "0x13", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_GCM_ASCONHASH256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x70", "protocol_version": "TLS", "kex_algorithm": "AES", "auth_algorithm": "128 GCM ASCONHASH256", "enc_algorithm": "", "hash_algorithm": "", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "TLS_AES_128_GCM_SHA256", "hex_byte_1": "0x13", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "TLS_AES_256_GCM_SHA384", "hex_byte_1": "0x13", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_ASCONAEAD128_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x6F", "protocol_version": "TLS", "kex_algorithm": "ASCONAEAD128", "auth_algorithm": "SHA256", "enc_algorithm": "", "hash_algorithm": "", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_CHACHA20_POLY1305_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x13", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.3"]}}, {"TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x19", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x17", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_3DES_EDE_CBC_SHA1", "openssl_name": "ADH-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x1B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_AES_128_CBC_SHA1", "openssl_name": "ADH-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x34", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_128_CBC_SHA256", "openssl_name": "ADH-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6C", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_128_GCM_SHA256", "openssl_name": "ADH-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA6", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_AES_256_CBC_SHA1", "openssl_name": "ADH-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x3A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_AES_256_CBC_SHA256", "openssl_name": "ADH-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6D", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DH_ANON_AES_256_GCM_SHA384", "openssl_name": "ADH-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA7", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x46", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x47", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_CBC_SHA1", "openssl_name": "ADH-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x46", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_CBC_SHA256", "openssl_name": "ADH-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBF", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x84", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_CBC_SHA1", "openssl_name": "ADH-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x89", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_CBC_SHA256", "openssl_name": "ADH-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC5", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DH_ANON_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x85", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1A", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_RC4_128_MD5": {"gnutls_name": "TLS_DH_ANON_ARCFOUR_128_MD5", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x18", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_anon_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "ADH-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x9B", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "anon", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0B", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0D", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x30", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x3E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA4", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x36", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x68", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA5", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x58", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x59", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x42", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xBB", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x82", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x85", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC1", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x83", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0C", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_DSS_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x97", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "DSS", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x11", "protocol_version": "TLS EXPORT", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-DSS-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x13", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_AES_128_CBC_SHA1", "openssl_name": "DHE-DSS-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x32", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_128_CBC_SHA256", "openssl_name": "DHE-DSS-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x40", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_128_GCM_SHA256", "openssl_name": "DHE-DSS-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_AES_256_CBC_SHA1", "openssl_name": "DHE-DSS-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x38", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_AES_256_CBC_SHA256", "openssl_name": "DHE-DSS-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6A", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_DSS_AES_256_GCM_SHA384", "openssl_name": "DHE-DSS-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x42", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x56", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x43", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x57", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA1", "openssl_name": "DHE-DSS-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x44", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-DSS-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBD", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x80", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA1", "openssl_name": "DHE-DSS-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x87", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_CBC_SHA256", "openssl_name": "DHE-DSS-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_DSS_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x81", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x12", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_DSS_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "DHE-DSS-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x99", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "DSS", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_AES_128_CBC_SHA1", "openssl_name": "DHE-PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x90", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_PSK_AES_128_CBC_SHA256", "openssl_name": "DHE-PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_CCM": {"gnutls_name": "TLS_DHE_PSK_AES_128_CCM", "openssl_name": "DHE-PSK-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA6", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_PSK_AES_128_GCM_SHA256", "openssl_name": "DHE-PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_PSK_AES_256_CBC_SHA1", "openssl_name": "DHE-PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x91", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_DHE_PSK_AES_256_CBC_SHA384", "openssl_name": "DHE-PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_CCM": {"gnutls_name": "TLS_DHE_PSK_AES_256_CCM", "openssl_name": "DHE-PSK-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA7", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_PSK_AES_256_GCM_SHA384", "openssl_name": "DHE-PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x66", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6C", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x67", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x96", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x90", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "DHE-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x97", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x91", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_DHE_PSK_CHACHA20_POLY1305", "openssl_name": "DHE-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA1", "openssl_name": "DHE-PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA256", "openssl_name": "DHE-PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB4", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_DHE_PSK_NULL_SHA384", "openssl_name": "DHE-PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB5", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_DHE_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x8E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x14", "protocol_version": "TLS EXPORT", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "DHE-RSA-DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x16", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_AES_128_CBC_SHA1", "openssl_name": "DHE-RSA-AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x33", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_128_CBC_SHA256", "openssl_name": "DHE-RSA-AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x67", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_DHE_RSA_AES_128_CCM", "openssl_name": "DHE-RSA-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_DHE_RSA_AES_128_CCM_8", "openssl_name": "DHE-RSA-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA2", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_128_GCM_SHA256", "openssl_name": "DHE-RSA-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x9E", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_AES_256_CBC_SHA1", "openssl_name": "DHE-RSA-AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x39", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_AES_256_CBC_SHA256", "openssl_name": "DHE-RSA-AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x6B", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_DHE_RSA_AES_256_CCM", "openssl_name": "DHE-RSA-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_DHE_RSA_AES_256_CCM_8", "openssl_name": "DHE-RSA-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA3", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_RSA_AES_256_GCM_SHA384", "openssl_name": "DHE-RSA-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0x9F", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x44", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x52", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x45", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x53", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA1", "openssl_name": "DHE-RSA-CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x45", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "DHE-RSA-CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBE", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7C", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1", "openssl_name": "DHE-RSA-CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x88", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_CBC_SHA256", "openssl_name": "DHE-RSA-CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC4", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_DHE_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7D", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_DHE_RSA_CHACHA20_POLY1305", "openssl_name": "DHE-RSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x15", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DHE_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "DHE-RSA-SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x9A", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0E", "protocol_version": "TLS EXPORT", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x10", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x31", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x3F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA0", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x37", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x69", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xA1", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x40", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x54", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x41", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x55", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x43", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xBC", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7E", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x86", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC2", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x0F", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_DH_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x98", "protocol_version": "TLS", "kex_algorithm": "DH", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB2", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB0", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_256_CCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB3", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECCPWD_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB1", "protocol_version": "TLS", "kex_algorithm": "ECCPWD", "auth_algorithm": "ECCPWD", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_3DES_EDE_CBC_SHA1", "openssl_name": "AECDH-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x17", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_AES_128_CBC_SHA1", "openssl_name": "AECDH-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x18", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDH_ANON_AES_256_CBC_SHA1", "openssl_name": "AECDH-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x19", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDH_ANON_NULL_SHA1", "openssl_name": "AECDH-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x15", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_anon_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDH_ANON_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x16", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "anon", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x25", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x26", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4A", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4B", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x74", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x88", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x75", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x89", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_NULL_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_ECDSA_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "ECDSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x08", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x09", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CBC_SHA256", "openssl_name": "ECDHE-ECDSA-AES128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x23", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CCM", "openssl_name": "ECDHE-ECDSA-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_CCM_8", "openssl_name": "ECDHE-ECDSA-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_128_GCM_SHA256", "openssl_name": "ECDHE-ECDSA-AES128-GCM-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x2B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CBC_SHA1", "openssl_name": "ECDHE-ECDSA-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x0A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CBC_SHA384", "openssl_name": "ECDHE-ECDSA-AES256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x24", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CCM", "openssl_name": "ECDHE-ECDSA-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_CCM_8", "openssl_name": "ECDHE-ECDSA-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAF", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_AES_256_GCM_SHA384", "openssl_name": "ECDHE-ECDSA-AES256-GCM-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x2C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x48", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x49", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x5D", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-ECDSA-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x72", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x86", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-ECDSA-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x73", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_ECDSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x87", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_ECDSA_CHACHA20_POLY1305", "openssl_name": "ECDHE-ECDSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_NULL_SHA1", "openssl_name": "ECDHE-ECDSA-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x06", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_ECDSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x07", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "ECDSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x34", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_AES_128_CBC_SHA1", "openssl_name": "ECDHE-PSK-AES128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x35", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_AES_128_CBC_SHA256", "openssl_name": "ECDHE-PSK-AES128-CBC-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x37", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_PSK_AES_256_CBC_SHA1", "openssl_name": "ECDHE-PSK-AES256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x36", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_AES_256_CBC_SHA384", "openssl_name": "ECDHE-PSK-AES256-CBC-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x38", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xD0", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x70", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x71", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x9A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x9B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_CHACHA20_POLY1305", "openssl_name": "ECDHE-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "recommended", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA1", "openssl_name": "ECDHE-PSK-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x39", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA256", "openssl_name": "ECDHE-PSK-NULL-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x3A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_ECDHE_PSK_NULL_SHA384", "openssl_name": "ECDHE-PSK-NULL-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x3B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x33", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "ECDHE-RSA-DES-CBC3-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x12", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_CBC_SHA1", "openssl_name": "ECDHE-RSA-AES128-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x13", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_CBC_SHA256", "openssl_name": "ECDHE-RSA-AES128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x27", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_AES_128_GCM_SHA256", "openssl_name": "ECDHE-RSA-AES128-GCM-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x2F", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_CBC_SHA1", "openssl_name": "ECDHE-RSA-AES256-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x14", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_CBC_SHA384", "openssl_name": "ECDHE-RSA-AES256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x28", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_AES_256_GCM_SHA384", "openssl_name": "ECDHE-RSA-AES256-GCM-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x30", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4C", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x60", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4D", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x61", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "ECDHE-RSA-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x76", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8A", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_256_CBC_SHA384", "openssl_name": "ECDHE-RSA-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x77", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_ECDHE_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8B", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_ECDHE_RSA_CHACHA20_POLY1305", "openssl_name": "ECDHE-RSA-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "secure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_NULL_SHA": {"gnutls_name": "TLS_ECDHE_RSA_NULL_SHA1", "openssl_name": "ECDHE-RSA-NULL-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x10", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDHE_RSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_ECDHE_RSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x11", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x29", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x31", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x2A", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x32", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4E", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x62", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x4F", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x63", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x78", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8C", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x79", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8D", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_NULL_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0B", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_ECDH_RSA_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x0C", "protocol_version": "TLS", "kex_algorithm": "ECDH", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_28147_CNT_IMIT": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "28147 CNT", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x00", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "KUZNYECHIK CTR", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x03", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "KUZNYECHIK MGM L", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "KUZNYECHIK MGM S", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "GOSTR341112 256", "auth_algorithm": "GOSTR341012", "enc_algorithm": "MAGMA CTR", "hash_algorithm": "GOSTR341112", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_MGM_L": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "MAGMA MGM L", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_GOSTR341112_256_WITH_MAGMA_MGM_S": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC1", "hex_byte_2": "0x06", "protocol_version": "TLS", "kex_algorithm": "ECDHE", "auth_algorithm": "-", "enc_algorithm": "MAGMA MGM S", "hash_algorithm": "-", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x29", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x26", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x2A", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x27", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x2B", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_EXPORT_WITH_RC4_40_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x28", "protocol_version": "TLS EXPORT", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 40", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_3DES_EDE_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x23", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1F", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_DES_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x22", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x1E", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_IDEA_CBC_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x25", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "IDEA CBC", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_IDEA_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x21", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "IDEA CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_RC4_128_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x24", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_KRB5_WITH_RC4_128_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x20", "protocol_version": "TLS", "kex_algorithm": "KRB5", "auth_algorithm": "KRB5", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_NULL_WITH_NULL_NULL": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x00", "protocol_version": "TLS", "kex_algorithm": "NULL", "auth_algorithm": "NULL", "enc_algorithm": "NULL", "hash_algorithm": "NULL", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_DHE_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_DHE_PSK_AES_128_CCM_8", "openssl_name": "DHE-PSK-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAA", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_DHE_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_DHE_PSK_AES_256_CCM_8", "openssl_name": "DHE-PSK-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "DHE", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8B", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_PSK_AES_128_CBC_SHA1", "openssl_name": "PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8C", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_PSK_AES_128_CBC_SHA256", "openssl_name": "PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CCM": {"gnutls_name": "TLS_PSK_AES_128_CCM", "openssl_name": "PSK-AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA4", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_PSK_AES_128_CCM_8", "openssl_name": "PSK-AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_PSK_AES_128_GCM_SHA256", "openssl_name": "PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xA8", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_PSK_AES_256_CBC_SHA1", "openssl_name": "PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x8D", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_PSK_AES_256_CBC_SHA384", "openssl_name": "PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAF", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CCM": {"gnutls_name": "TLS_PSK_AES_256_CCM", "openssl_name": "PSK-AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0xA5", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_PSK_AES_256_CCM_8", "openssl_name": "PSK-AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_PSK_AES_256_GCM_SHA384", "openssl_name": "PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xA9", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x64", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6A", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x65", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6B", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x94", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8E", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x95", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x8F", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_PSK_CHACHA20_POLY1305", "openssl_name": "PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAB", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_PSK_NULL_SHA1", "openssl_name": "PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2C", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_PSK_NULL_SHA256", "openssl_name": "PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB0", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_PSK_NULL_SHA384", "openssl_name": "PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB1", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x8A", "protocol_version": "TLS", "kex_algorithm": "PSK", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_DES40_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x08", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "DES40 CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x06", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC2 CBC 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_EXPORT_WITH_RC4_40_MD5": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x03", "protocol_version": "TLS EXPORT", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 40", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_3DES_EDE_CBC_SHA1", "openssl_name": "RSA-PSK-3DES-EDE-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x93", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_AES_128_CBC_SHA1", "openssl_name": "RSA-PSK-AES128-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x94", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_PSK_AES_128_CBC_SHA256", "openssl_name": "RSA-PSK-AES128-CBC-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB6", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_PSK_AES_128_GCM_SHA256", "openssl_name": "RSA-PSK-AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xAC", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_RSA_PSK_AES_256_CBC_SHA1", "openssl_name": "RSA-PSK-AES256-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x95", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_CBC_SHA384": {"gnutls_name": "TLS_RSA_PSK_AES_256_CBC_SHA384", "openssl_name": "RSA-PSK-AES256-CBC-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB7", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_PSK_AES_256_GCM_SHA384", "openssl_name": "RSA-PSK-AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xAD", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x68", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6E", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x69", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x6F", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_128_CBC_SHA256", "openssl_name": "RSA-PSK-CAMELLIA128-SHA256", "hex_byte_1": "0xC0", "hex_byte_2": "0x98", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x92", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_256_CBC_SHA384", "openssl_name": "RSA-PSK-CAMELLIA256-SHA384", "hex_byte_1": "0xC0", "hex_byte_2": "0x99", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_PSK_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x93", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256": {"gnutls_name": "TLS_RSA_PSK_CHACHA20_POLY1305", "openssl_name": "RSA-PSK-CHACHA20-POLY1305", "hex_byte_1": "0xCC", "hex_byte_2": "0xAE", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "CHACHA20 POLY1305", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA1", "openssl_name": "RSA-PSK-NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2E", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA256": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA256", "openssl_name": "RSA-PSK-NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xB8", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_NULL_SHA384": {"gnutls_name": "TLS_RSA_PSK_NULL_SHA384", "openssl_name": "RSA-PSK-NULL-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0xB9", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_PSK_WITH_RC4_128_SHA": {"gnutls_name": "TLS_RSA_PSK_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x92", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "PSK", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "DES-CBC3-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x0A", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_RSA_AES_128_CBC_SHA1", "openssl_name": "AES128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x2F", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_AES_128_CBC_SHA256", "openssl_name": "AES128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CCM": {"gnutls_name": "TLS_RSA_AES_128_CCM", "openssl_name": "AES128-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_CCM_8": {"gnutls_name": "TLS_RSA_AES_128_CCM_8", "openssl_name": "AES128-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA0", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_AES_128_GCM_SHA256", "openssl_name": "AES128-GCM-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x9C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_RSA_AES_256_CBC_SHA1", "openssl_name": "AES256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x35", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CBC_SHA256": {"gnutls_name": "TLS_RSA_AES_256_CBC_SHA256", "openssl_name": "AES256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CCM": {"gnutls_name": "TLS_RSA_AES_256_CCM", "openssl_name": "AES256-CCM", "hex_byte_1": "0xC0", "hex_byte_2": "0x9D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_CCM_8": {"gnutls_name": "TLS_RSA_AES_256_CCM_8", "openssl_name": "AES256-CCM8", "hex_byte_1": "0xC0", "hex_byte_2": "0xA1", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 CCM 8", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_AES_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_AES_256_GCM_SHA384", "openssl_name": "AES256-GCM-SHA384", "hex_byte_1": "0x00", "hex_byte_2": "0x9D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "AES 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_128_CBC_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3C", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_128_GCM_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x50", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_256_CBC_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x3D", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 CBC", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_ARIA_256_GCM_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x51", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "ARIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA": {"gnutls_name": "TLS_RSA_CAMELLIA_128_CBC_SHA1", "openssl_name": "CAMELLIA128-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x41", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_128_CBC_SHA256", "openssl_name": "CAMELLIA128-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xBA", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_128_GCM_SHA256", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7A", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 128 GCM", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA": {"gnutls_name": "TLS_RSA_CAMELLIA_256_CBC_SHA1", "openssl_name": "CAMELLIA256-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x84", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256": {"gnutls_name": "TLS_RSA_CAMELLIA_256_CBC_SHA256", "openssl_name": "CAMELLIA256-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0xC0", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 CBC", "hash_algorithm": "SHA256", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384": {"gnutls_name": "TLS_RSA_CAMELLIA_256_GCM_SHA384", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0x7B", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "CAMELLIA 256 GCM", "hash_algorithm": "SHA384", "security": "weak", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_DES_CBC_SHA": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x09", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "DES CBC", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_IDEA_CBC_SHA": {"gnutls_name": "", "openssl_name": "IDEA-CBC-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x07", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "IDEA CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_MD5": {"gnutls_name": "TLS_RSA_NULL_MD5", "openssl_name": "NULL-MD5", "hex_byte_1": "0x00", "hex_byte_2": "0x01", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_SHA": {"gnutls_name": "TLS_RSA_NULL_SHA1", "openssl_name": "NULL-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x02", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_NULL_SHA256": {"gnutls_name": "TLS_RSA_NULL_SHA256", "openssl_name": "NULL-SHA256", "hex_byte_1": "0x00", "hex_byte_2": "0x3B", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_RC4_128_MD5": {"gnutls_name": "TLS_RSA_ARCFOUR_128_MD5", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x04", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "MD5", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_RC4_128_SHA": {"gnutls_name": "TLS_RSA_ARCFOUR_128_SHA1", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0x05", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "RC4 128", "hash_algorithm": "SHA", "security": "insecure", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_RSA_WITH_SEED_CBC_SHA": {"gnutls_name": "", "openssl_name": "SEED-SHA", "hex_byte_1": "0x00", "hex_byte_2": "0x96", "protocol_version": "TLS", "kex_algorithm": "RSA", "auth_algorithm": "RSA", "enc_algorithm": "SEED CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SHA256_SHA256": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB4", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "SHA256", "enc_algorithm": "NULL", "hash_algorithm": "SHA256", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SHA384_SHA384": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0xC0", "hex_byte_2": "0xB5", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "SHA384", "enc_algorithm": "NULL", "hash_algorithm": "SHA384", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SM4_CCM_SM3": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC7", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "SM4 CCM", "hash_algorithm": "SM3", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SM4_GCM_SM3": {"gnutls_name": "", "openssl_name": "", "hex_byte_1": "0x00", "hex_byte_2": "0xC6", "protocol_version": "TLS", "kex_algorithm": "-", "auth_algorithm": "-", "enc_algorithm": "SM4 GCM", "hash_algorithm": "SM3", "security": "insecure", "tls_version": ["TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-DSS-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1C", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_AES_128_CBC_SHA1", "openssl_name": "SRP-DSS-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1F", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_DSS_AES_256_CBC_SHA1", "openssl_name": "SRP-DSS-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x22", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA DSS", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-RSA-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1B", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_AES_128_CBC_SHA1", "openssl_name": "SRP-RSA-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1E", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_RSA_AES_256_CBC_SHA1", "openssl_name": "SRP-RSA-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x21", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA RSA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_3DES_EDE_CBC_SHA1", "openssl_name": "SRP-3DES-EDE-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1A", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "3DES EDE CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_AES_128_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_AES_128_CBC_SHA1", "openssl_name": "SRP-AES-128-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x1D", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "AES 128 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}, {"TLS_SRP_SHA_WITH_AES_256_CBC_SHA": {"gnutls_name": "TLS_SRP_SHA_AES_256_CBC_SHA1", "openssl_name": "SRP-AES-256-CBC-SHA", "hex_byte_1": "0xC0", "hex_byte_2": "0x20", "protocol_version": "TLS", "kex_algorithm": "SRP", "auth_algorithm": "SHA", "enc_algorithm": "AES 256 CBC", "hash_algorithm": "SHA", "security": "weak", "tls_version": ["TLS1.0", "TLS1.1", "TLS1.2", "TLS1.3"]}}]} \ No newline at end of file diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java index 5461d068d..738fd0e9b 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCipherMapper.java @@ -26,14 +26,18 @@ import com.ibm.mapper.model.algorithms.Camellia; import com.ibm.mapper.model.algorithms.ChaCha20; import com.ibm.mapper.model.algorithms.ChaCha20Poly1305; +import com.ibm.mapper.model.algorithms.DES; import com.ibm.mapper.model.algorithms.Fernet; import com.ibm.mapper.model.algorithms.IDEA; +import com.ibm.mapper.model.algorithms.RC2; import com.ibm.mapper.model.algorithms.RC4; import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.algorithms.SEED; import com.ibm.mapper.model.algorithms.SM4; +import com.ibm.mapper.model.algorithms.Salsa20; import com.ibm.mapper.model.algorithms.TripleDES; import com.ibm.mapper.model.algorithms.cast.CAST128; +import com.ibm.mapper.model.mode.GCM; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; import javax.annotation.Nonnull; @@ -52,18 +56,26 @@ public final class PycaCipherMapper implements IMapper { case "AES" -> Optional.of(new AES(detectionLocation)); case "AES128" -> Optional.of(new AES(128, detectionLocation)); case "AES256" -> Optional.of(new AES(256, detectionLocation)); + case "AES128_GCM" -> + Optional.of(new AES(128, new GCM(detectionLocation), detectionLocation)); + case "AES256_GCM" -> + Optional.of(new AES(256, new GCM(detectionLocation), detectionLocation)); case "CAMELLIA" -> Optional.of(new Camellia(detectionLocation)); - case "TRIPLEDES" -> Optional.of(new TripleDES(detectionLocation)); + case "TRIPLEDES", "3DES" -> Optional.of(new TripleDES(detectionLocation)); + case "DES" -> Optional.of(new DES(detectionLocation)); case "CAST5" -> Optional.of(new CAST128(detectionLocation)); case "SEED" -> Optional.of(new SEED(detectionLocation)); case "SM4" -> Optional.of(new SM4(detectionLocation)); case "BLOWFISH" -> Optional.of(new Blowfish(detectionLocation)); case "IDEA" -> Optional.of(new IDEA(detectionLocation)); case "CHACHA20" -> Optional.of(new ChaCha20(detectionLocation)); - case "ARC4" -> Optional.of(new RC4(detectionLocation)); + case "SALSA20" -> Optional.of(new Salsa20(detectionLocation)); + case "ARC4", "RC4" -> Optional.of(new RC4(detectionLocation)); + case "RC2" -> Optional.of(new RC2(detectionLocation)); case "FERNET" -> Optional.of(new Fernet(detectionLocation)); case "RSA" -> Optional.of(new RSA(detectionLocation)); - case "CHACHA20POLY1305" -> Optional.of(new ChaCha20Poly1305(detectionLocation)); + case "CHACHA20POLY1305", "CHACHA20_POLY1305" -> + Optional.of(new ChaCha20Poly1305(detectionLocation)); default -> Optional.empty(); }; } diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCurveMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCurveMapper.java new file mode 100644 index 000000000..11b3fec9f --- /dev/null +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaCurveMapper.java @@ -0,0 +1,105 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.mapper.mapper.pyca; + +import com.ibm.mapper.mapper.IMapper; +import com.ibm.mapper.model.Algorithm; +import com.ibm.mapper.model.EllipticCurveAlgorithm; +import com.ibm.mapper.model.curves.Brainpoolp256r1; +import com.ibm.mapper.model.curves.Brainpoolp384r1; +import com.ibm.mapper.model.curves.Brainpoolp512r1; +import com.ibm.mapper.model.curves.Curve25519; +import com.ibm.mapper.model.curves.Curve448; +import com.ibm.mapper.model.curves.Secp192r1; +import com.ibm.mapper.model.curves.Secp224r1; +import com.ibm.mapper.model.curves.Secp256r1; +import com.ibm.mapper.model.curves.Secp384r1; +import com.ibm.mapper.model.curves.Secp521r1; +import com.ibm.mapper.model.curves.Sect163k1; +import com.ibm.mapper.model.curves.Sect163r2; +import com.ibm.mapper.model.curves.Sect233k1; +import com.ibm.mapper.model.curves.Sect233r1; +import com.ibm.mapper.model.curves.Sect283k1; +import com.ibm.mapper.model.curves.Sect283r1; +import com.ibm.mapper.model.curves.Sect409k1; +import com.ibm.mapper.model.curves.Sect409r1; +import com.ibm.mapper.model.curves.Sect571k1; +import com.ibm.mapper.model.curves.Sect571r1; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class PycaCurveMapper implements IMapper { + + @Nonnull + @Override + public Optional parse( + @Nullable String str, @Nonnull DetectionLocation detectionLocation) { + if (str == null) { + return Optional.empty(); + } + + @Nonnull String curve = str; + return switch (curve.toUpperCase().trim()) { + case "SECP192R1", "PRIME192V1", "P-192", "P192", "NIST P-192" -> + Optional.of(new EllipticCurveAlgorithm(new Secp192r1(detectionLocation))); + case "SECP224R1", "PRIME224V1", "P-224", "P224", "NIST P-224" -> + Optional.of(new EllipticCurveAlgorithm(new Secp224r1(detectionLocation))); + case "SECP256R1", "PRIME256V1", "P-256", "P256", "NIST P-256" -> + Optional.of(new EllipticCurveAlgorithm(new Secp256r1(detectionLocation))); + case "SECP384R1", "PRIME384V1", "P-384", "P384", "NIST P-384" -> + Optional.of(new EllipticCurveAlgorithm(new Secp384r1(detectionLocation))); + case "SECP512R1", "PRIME512V1", "P-512", "P512", "NIST P-512" -> + Optional.of(new EllipticCurveAlgorithm(new Secp521r1(detectionLocation))); + case "ED25519", "CURVE25519" -> + Optional.of(new EllipticCurveAlgorithm(new Curve25519(detectionLocation))); + case "ED448", "CURVE448" -> + Optional.of(new EllipticCurveAlgorithm(new Curve448(detectionLocation))); + case "BRAINPOOLP256R1" -> + Optional.of(new EllipticCurveAlgorithm(new Brainpoolp256r1(detectionLocation))); + case "BRAINPOOLP384R1" -> + Optional.of(new EllipticCurveAlgorithm(new Brainpoolp384r1(detectionLocation))); + case "BRAINPOOLP512R1" -> + Optional.of(new EllipticCurveAlgorithm(new Brainpoolp512r1(detectionLocation))); + case "SECT571K1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect571k1(detectionLocation))); + case "SECT409K1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect409k1(detectionLocation))); + case "SECT283K1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect283k1(detectionLocation))); + case "SECT233K1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect233k1(detectionLocation))); + case "SECT163K1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect163k1(detectionLocation))); + case "SECT571R1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect571r1(detectionLocation))); + case "SECT409R1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect409r1(detectionLocation))); + case "SECT283R1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect283r1(detectionLocation))); + case "SECT233R1" -> + Optional.of(new EllipticCurveAlgorithm(new Sect233r1(detectionLocation))); + case "SECT163R2" -> + Optional.of(new EllipticCurveAlgorithm(new Sect163r2(detectionLocation))); + default -> Optional.empty(); + }; + } +} diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java index 8e2a1ca3e..b213ba7fa 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaDigestMapper.java @@ -21,14 +21,22 @@ import com.ibm.mapper.mapper.IMapper; import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.algorithms.KMAC; +import com.ibm.mapper.model.algorithms.KangarooTwelve; +import com.ibm.mapper.model.algorithms.Keccak; +import com.ibm.mapper.model.algorithms.MD2; +import com.ibm.mapper.model.algorithms.MD4; import com.ibm.mapper.model.algorithms.MD5; import com.ibm.mapper.model.algorithms.Poly1305; +import com.ibm.mapper.model.algorithms.RIPEMD; import com.ibm.mapper.model.algorithms.SHA; import com.ibm.mapper.model.algorithms.SHA2; import com.ibm.mapper.model.algorithms.SHA3; import com.ibm.mapper.model.algorithms.SM3; +import com.ibm.mapper.model.algorithms.TupleHash; import com.ibm.mapper.model.algorithms.blake.BLAKE2b; import com.ibm.mapper.model.algorithms.blake.BLAKE2s; +import com.ibm.mapper.model.algorithms.shake.CSHAKE; import com.ibm.mapper.model.algorithms.shake.SHAKE; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; @@ -59,11 +67,22 @@ public final class PycaDigestMapper implements IMapper { case "SHA3_512" -> Optional.of(new SHA3(512, detectionLocation)); case "SHAKE128" -> Optional.of(new SHAKE(128, detectionLocation)); case "SHAKE256" -> Optional.of(new SHAKE(256, detectionLocation)); + case "MD2" -> Optional.of(new MD2(detectionLocation)); + case "MD4" -> Optional.of(new MD4(detectionLocation)); case "MD5" -> Optional.of(new MD5(detectionLocation)); case "BLAKE2B" -> Optional.of(new BLAKE2b(false, detectionLocation)); case "BLAKE2S" -> Optional.of(new BLAKE2s(false, detectionLocation)); case "SM3" -> Optional.of(new SM3(detectionLocation)); case "POLY1305" -> Optional.of(new Poly1305(detectionLocation)); + case "RIPEMD160" -> Optional.of(new RIPEMD(160, detectionLocation)); + case "TUPLEHASH128" -> Optional.of(new TupleHash(128, detectionLocation)); + case "TUPLEHASH256" -> Optional.of(new TupleHash(256, detectionLocation)); + case "KMAC128" -> Optional.of(new KMAC(128, detectionLocation)); + case "KMAC256" -> Optional.of(new KMAC(256, detectionLocation)); + case "KECCAK" -> Optional.of(new Keccak(detectionLocation)); + case "CSHAKE128" -> Optional.of(new CSHAKE(128, detectionLocation)); + case "CSHAKE256" -> Optional.of(new CSHAKE(256, detectionLocation)); + case "KANGAROOTWELVE" -> Optional.of(new KangarooTwelve(detectionLocation)); default -> Optional.empty(); }; } diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java index 777eca70b..20cc3e60b 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/pyca/PycaMacMapper.java @@ -28,9 +28,11 @@ import com.ibm.mapper.model.algorithms.ChaCha20; import com.ibm.mapper.model.algorithms.Fernet; import com.ibm.mapper.model.algorithms.IDEA; +import com.ibm.mapper.model.algorithms.MD2; import com.ibm.mapper.model.algorithms.MD5; import com.ibm.mapper.model.algorithms.Poly1305; import com.ibm.mapper.model.algorithms.RC4; +import com.ibm.mapper.model.algorithms.RIPEMD; import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.algorithms.SEED; import com.ibm.mapper.model.algorithms.SHA; @@ -42,6 +44,7 @@ import com.ibm.mapper.model.algorithms.blake.BLAKE2b; import com.ibm.mapper.model.algorithms.blake.BLAKE2s; import com.ibm.mapper.model.algorithms.cast.CAST128; +import com.ibm.mapper.model.algorithms.shake.CSHAKE; import com.ibm.mapper.model.algorithms.shake.SHAKE; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; @@ -104,6 +107,7 @@ public class PycaMacMapper implements IMapper { case "SHAKE128" -> Optional.of(new SHAKE(Mac.class, new SHAKE(128, detectionLocation))); case "SHAKE256" -> Optional.of(new SHAKE(Mac.class, new SHAKE(256, detectionLocation))); case "MD5" -> Optional.of(new MD5(Mac.class, detectionLocation)); + case "MD2" -> Optional.of(new MD2(Mac.class, detectionLocation)); case "BLAKE2B" -> Optional.of(new BLAKE2b(Mac.class, new BLAKE2b(false, detectionLocation))); case "BLAKE2S" -> @@ -111,6 +115,12 @@ public class PycaMacMapper implements IMapper { case "SM3" -> Optional.of(new SM3(Mac.class, new SM3(detectionLocation))); case "POLY1305" -> Optional.of(new Poly1305(Mac.class, new Poly1305(detectionLocation))); + case "RIPEMD160" -> + Optional.of(new RIPEMD(Mac.class, new RIPEMD(160, detectionLocation))); + case "CSHAKE128" -> + Optional.of(new CSHAKE(Mac.class, new CSHAKE(128, detectionLocation))); + case "CSHAKE256" -> + Optional.of(new CSHAKE(Mac.class, new CSHAKE(256, detectionLocation))); default -> Optional.empty(); }; } diff --git a/mapper/src/main/java/com/ibm/mapper/mapper/ssl/json/JsonCipherSuites.java b/mapper/src/main/java/com/ibm/mapper/mapper/ssl/json/JsonCipherSuites.java index b94d3d1a3..8bcc4a6bf 100644 --- a/mapper/src/main/java/com/ibm/mapper/mapper/ssl/json/JsonCipherSuites.java +++ b/mapper/src/main/java/com/ibm/mapper/mapper/ssl/json/JsonCipherSuites.java @@ -41,6 +41,17 @@ private JsonCipherSuites() { null, "AES 128 CCM 8", "SHA256")), + Map.entry( + "TLS_AES_128_CCM_ASCONHASH256", + new JsonCipherSuite( + "TLS_AES_128_CCM_ASCONHASH256", + null, + null, + new String[] {"0x00", "0x71"}, + "AES", + "128 CCM ASCONHASH256", + null, + null)), Map.entry( "TLS_AES_128_CCM_SHA256", new JsonCipherSuite( @@ -52,6 +63,17 @@ private JsonCipherSuites() { null, "AES 128 CCM", "SHA256")), + Map.entry( + "TLS_AES_128_GCM_ASCONHASH256", + new JsonCipherSuite( + "TLS_AES_128_GCM_ASCONHASH256", + null, + null, + new String[] {"0x00", "0x70"}, + "AES", + "128 GCM ASCONHASH256", + null, + null)), Map.entry( "TLS_AES_128_GCM_SHA256", new JsonCipherSuite( @@ -74,6 +96,17 @@ private JsonCipherSuites() { null, "AES 256 GCM", "SHA384")), + Map.entry( + "TLS_ASCONAEAD128_SHA256", + new JsonCipherSuite( + "TLS_ASCONAEAD128_SHA256", + null, + null, + new String[] {"0x00", "0x6F"}, + "ASCONAEAD128", + "SHA256", + null, + null)), Map.entry( "TLS_CHACHA20_POLY1305_SHA256", new JsonCipherSuite( diff --git a/mapper/src/main/java/com/ibm/mapper/model/algorithms/RIPEMD.java b/mapper/src/main/java/com/ibm/mapper/model/algorithms/RIPEMD.java index 4ed5f0860..15766ae7d 100644 --- a/mapper/src/main/java/com/ibm/mapper/model/algorithms/RIPEMD.java +++ b/mapper/src/main/java/com/ibm/mapper/model/algorithms/RIPEMD.java @@ -22,6 +22,7 @@ import com.ibm.mapper.model.Algorithm; import com.ibm.mapper.model.DigestSize; import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.IPrimitive; import com.ibm.mapper.model.MessageDigest; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; @@ -72,4 +73,8 @@ public RIPEMD(int digestSize, @Nonnull DetectionLocation detectionLocation) { this(detectionLocation); this.put(new DigestSize(digestSize, detectionLocation)); } + + public RIPEMD(@Nonnull final Class asKind, @Nonnull RIPEMD ripemd) { + super(ripemd, asKind); + } } diff --git a/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignatureReorganizer.java b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignatureReorganizer.java index 5a4708993..f59e8a204 100644 --- a/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignatureReorganizer.java +++ b/mapper/src/main/java/com/ibm/mapper/reorganizer/rules/SignatureReorganizer.java @@ -35,7 +35,6 @@ import com.ibm.mapper.reorganizer.builder.ReorganizerRuleBuilder; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Optional; import javax.annotation.Nonnull; @@ -194,12 +193,17 @@ public static IReorganizerRule moveNodesFromUnderFunctionalityUnderNode( .flatMap(p -> p.hasChildOfType(underNodeClazz)) .ifPresent( n -> { - for (Map.Entry, INode> - childKeyValue : - node.getChildren().entrySet()) { - n.put(childKeyValue.getValue()); - node.removeChildOfType(childKeyValue.getKey()); - } + // Avoids java.util.ConcurrentModificationException + // thrown by original code + node.getChildren().values().forEach(n::put); + node.getChildren().clear(); + // for (Map.Entry, INode> + // childKeyValue : + // node.getChildren().entrySet()) { + // n.put(childKeyValue.getValue()); + // + // node.removeChildOfType(childKeyValue.getKey()); + // } }); return null; }); @@ -252,12 +256,17 @@ public static IReorganizerRule moveNodesFromUnderFunctionalityUnderParent( Optional.ofNullable(parent) .ifPresent( p -> { - for (Map.Entry, INode> - childKeyValue : - node.getChildren().entrySet()) { - p.put(childKeyValue.getValue()); - node.removeChildOfType(childKeyValue.getKey()); - } + // Avoids java.util.ConcurrentModificationException + // thrown by original code + node.getChildren().values().forEach(p::put); + node.getChildren().clear(); + // for (Map.Entry, INode> + // childKeyValue : + // node.getChildren().entrySet()) { + // p.put(childKeyValue.getValue()); + // + // node.removeChildOfType(childKeyValue.getKey()); + // } }); return null; }); diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/PythonDetectionRules.java b/python/src/main/java/com/ibm/plugin/rules/detection/PythonDetectionRules.java index b6453be38..eeb3c16ce 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/PythonDetectionRules.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/PythonDetectionRules.java @@ -20,20 +20,28 @@ package com.ibm.plugin.rules.detection; import com.ibm.engine.rule.IDetectionRule; -import com.ibm.plugin.rules.detection.aead.PycaAEAD; -import com.ibm.plugin.rules.detection.aead.PycaAES; -import com.ibm.plugin.rules.detection.asymmetric.PycaDSA; -import com.ibm.plugin.rules.detection.asymmetric.PycaDiffieHellman; -import com.ibm.plugin.rules.detection.asymmetric.PycaEllipticCurve; -import com.ibm.plugin.rules.detection.asymmetric.PycaRSA; -import com.ibm.plugin.rules.detection.asymmetric.PycaSign; -import com.ibm.plugin.rules.detection.fernet.PycaFernet; -import com.ibm.plugin.rules.detection.hash.PycaHash; -import com.ibm.plugin.rules.detection.kdf.PycaKDF; -import com.ibm.plugin.rules.detection.keyagreement.PycaKeyAgreement; -import com.ibm.plugin.rules.detection.mac.PycaMAC; -import com.ibm.plugin.rules.detection.symmetric.PycaCipher; -import com.ibm.plugin.rules.detection.wrapping.PycaWrapping; +import com.ibm.plugin.rules.detection.pyca.aead.PycaAEAD; +import com.ibm.plugin.rules.detection.pyca.aead.PycaAES; +import com.ibm.plugin.rules.detection.pyca.asymmetric.PycaDSA; +import com.ibm.plugin.rules.detection.pyca.asymmetric.PycaDiffieHellman; +import com.ibm.plugin.rules.detection.pyca.asymmetric.PycaEllipticCurve; +import com.ibm.plugin.rules.detection.pyca.asymmetric.PycaRSA; +import com.ibm.plugin.rules.detection.pyca.asymmetric.PycaSign; +import com.ibm.plugin.rules.detection.pyca.fernet.PycaFernet; +import com.ibm.plugin.rules.detection.pyca.hash.PycaHash; +import com.ibm.plugin.rules.detection.pyca.kdf.PycaKDF; +import com.ibm.plugin.rules.detection.pyca.keyagreement.PycaKeyAgreement; +import com.ibm.plugin.rules.detection.pyca.mac.PycaMAC; +import com.ibm.plugin.rules.detection.pyca.symmetric.PycaCipher; +import com.ibm.plugin.rules.detection.pyca.wrapping.PycaWrapping; +import com.ibm.plugin.rules.detection.pycrypto.cipher.PythonCryptoCipher; +import com.ibm.plugin.rules.detection.pycrypto.hash.PythonCryptoHash; +import com.ibm.plugin.rules.detection.pycrypto.kdf.PythonCryptoKDF; +import com.ibm.plugin.rules.detection.pycrypto.keyagreement.PythonCryptoKeyAgreement; +import com.ibm.plugin.rules.detection.pycrypto.mac.PythonCryptoMac; +import com.ibm.plugin.rules.detection.pycrypto.publickey.PythonCryptoPublicKey; +import com.ibm.plugin.rules.detection.pycrypto.random.PythonCryptoRandom; +import com.ibm.plugin.rules.detection.pycrypto.signature.PythonCryptoSignature; import java.util.List; import java.util.function.Supplier; import java.util.stream.Stream; @@ -70,7 +78,15 @@ private static List> buildRules() { PycaMAC.rules().stream(), PycaWrapping.rules().stream(), PycaKDF.rules().stream(), - PycaFernet.rules().stream()) + PycaFernet.rules().stream(), + PythonCryptoHash.rules().stream(), + PythonCryptoMac.rules().stream(), + PythonCryptoRandom.rules().stream(), + PythonCryptoCipher.rules().stream(), + PythonCryptoPublicKey.rules().stream(), + PythonCryptoSignature.rules().stream(), + PythonCryptoKDF.rules().stream(), + PythonCryptoKeyAgreement.rules().stream()) .flatMap(i -> i) .toList(); } diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAEAD.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAEAD.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAEAD.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAEAD.java index 1b1a9812a..5c15bc309 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAEAD.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAEAD.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.aead; +package com.ibm.plugin.rules.detection.pyca.aead; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.KeyAction; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAES.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAES.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAES.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAES.java index 93d7dc0c5..85e16955f 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/aead/PycaAES.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAES.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.aead; +package com.ibm.plugin.rules.detection.pyca.aead; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.Size; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDSA.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDSA.java similarity index 97% rename from python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDSA.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDSA.java index 51211987f..e53f390df 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDSA.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDSA.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric; +package com.ibm.plugin.rules.detection.pyca.asymmetric; import static com.ibm.engine.detection.MethodMatcher.ANY; @@ -33,7 +33,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import com.ibm.plugin.rules.detection.Memoize; -import com.ibm.plugin.rules.detection.hash.PycaHash; +import com.ibm.plugin.rules.detection.pyca.hash.PycaHash; import java.util.List; import java.util.Map; import java.util.function.Supplier; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDiffieHellman.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDiffieHellman.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDiffieHellman.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDiffieHellman.java index ae1fef88d..cabfe6b03 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaDiffieHellman.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaDiffieHellman.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric; +package com.ibm.plugin.rules.detection.pyca.asymmetric; import static com.ibm.engine.detection.MethodMatcher.ANY; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaEllipticCurve.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaEllipticCurve.java index 195cc53b5..3e1842f6f 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaEllipticCurve.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaEllipticCurve.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric; +package com.ibm.plugin.rules.detection.pyca.asymmetric; import static com.ibm.engine.detection.MethodMatcher.ANY; @@ -34,7 +34,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import com.ibm.plugin.rules.detection.Memoize; -import com.ibm.plugin.rules.detection.hash.PycaHash; +import com.ibm.plugin.rules.detection.pyca.hash.PycaHash; import java.util.List; import java.util.Map; import java.util.function.Supplier; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaRSA.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaRSA.java index 8eeaf5766..4d3364e26 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaRSA.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaRSA.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric; +package com.ibm.plugin.rules.detection.pyca.asymmetric; import static com.ibm.engine.detection.MethodMatcher.ANY; @@ -37,7 +37,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import com.ibm.plugin.rules.detection.Memoize; -import com.ibm.plugin.rules.detection.hash.PycaHash; +import com.ibm.plugin.rules.detection.pyca.hash.PycaHash; import java.util.List; import java.util.Map; import java.util.function.Supplier; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaSign.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaSign.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaSign.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaSign.java index 6b50bf24a..7e910e632 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/asymmetric/PycaSign.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/asymmetric/PycaSign.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric; +package com.ibm.plugin.rules.detection.pyca.asymmetric; import com.ibm.engine.model.KeyAction; import com.ibm.engine.model.context.PrivateKeyContext; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/fernet/PycaFernet.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernet.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/fernet/PycaFernet.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernet.java index a1eb299f9..4a4fcf607 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/fernet/PycaFernet.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernet.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.fernet; +package com.ibm.plugin.rules.detection.pyca.fernet; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.KeyAction; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/hash/PycaHash.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHash.java similarity index 93% rename from python/src/main/java/com/ibm/plugin/rules/detection/hash/PycaHash.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHash.java index 27aead4c7..f3da3342f 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/hash/PycaHash.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHash.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.hash; +package com.ibm.plugin.rules.detection.pyca.hash; import com.ibm.engine.model.context.DigestContext; import com.ibm.engine.model.factory.AlgorithmFactory; @@ -116,7 +116,16 @@ private static List> buildRules() { } @Nonnull - public static List> wrapperRules() { + private static final Supplier>> WRAPPER_RULES = + Memoize.of(PycaHash::wrapperRule); + + @Nonnull + public static List> wrapperRule() { return List.of(HASH_WRAPPER); } + + @Nonnull + public static List> wrapperRules() { + return WRAPPER_RULES.get(); + } } diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKDF.java similarity index 99% rename from python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKDF.java index 2c2dc8a3c..ae099981a 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/kdf/PycaKDF.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKDF.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static com.ibm.engine.detection.MethodMatcher.ANY; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreement.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreement.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreement.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreement.java index 127c0bca2..13d48c151 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreement.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreement.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.keyagreement; +package com.ibm.plugin.rules.detection.pyca.keyagreement; import com.ibm.engine.model.KeyAction; import com.ibm.engine.model.context.KeyAgreementContext; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/mac/PycaMAC.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMAC.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/mac/PycaMAC.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMAC.java index 4cbedf859..20b477869 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/mac/PycaMAC.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMAC.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.mac; +package com.ibm.plugin.rules.detection.pyca.mac; import static com.ibm.engine.detection.MethodMatcher.ANY; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/padding/PycaPadding.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPadding.java similarity index 97% rename from python/src/main/java/com/ibm/plugin/rules/detection/padding/PycaPadding.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPadding.java index 404367ff3..314b90058 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/padding/PycaPadding.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPadding.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.padding; +package com.ibm.plugin.rules.detection.pyca.padding; import com.ibm.engine.model.Size; import com.ibm.engine.model.context.CipherContext; @@ -26,7 +26,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import com.ibm.plugin.rules.detection.Memoize; -import com.ibm.plugin.rules.detection.symmetric.PycaCipher; +import com.ibm.plugin.rules.detection.pyca.symmetric.PycaCipher; import java.util.Arrays; import java.util.LinkedList; import java.util.List; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher.java similarity index 97% rename from python/src/main/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher.java index 2438d9eaf..06b8d0b0e 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.symmetric; +package com.ibm.plugin.rules.detection.pyca.symmetric; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.context.CipherContext; @@ -27,7 +27,7 @@ import com.ibm.engine.rule.IDetectionRule; import com.ibm.engine.rule.builder.DetectionRuleBuilder; import com.ibm.plugin.rules.detection.Memoize; -import com.ibm.plugin.rules.detection.padding.PycaPadding; +import com.ibm.plugin.rules.detection.pyca.padding.PycaPadding; import java.util.Arrays; import java.util.LinkedList; import java.util.List; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/wrapping/PycaWrapping.java b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrapping.java similarity index 98% rename from python/src/main/java/com/ibm/plugin/rules/detection/wrapping/PycaWrapping.java rename to python/src/main/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrapping.java index 7ffd52972..18f782847 100644 --- a/python/src/main/java/com/ibm/plugin/rules/detection/wrapping/PycaWrapping.java +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrapping.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.wrapping; +package com.ibm.plugin.rules.detection.pyca.wrapping; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.context.CipherContext; diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PythonCryptoCipher.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PythonCryptoCipher.java new file mode 100644 index 000000000..892cdf56e --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PythonCryptoCipher.java @@ -0,0 +1,396 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static com.ibm.engine.detection.MethodMatcher.ANY; + +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.engine.model.factory.AlgorithmFactory; +import com.ibm.engine.model.factory.CipherActionFactory; +import com.ibm.engine.model.factory.ModeFactory; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import com.ibm.plugin.rules.detection.pycrypto.publickey.PythonCryptoPublicKey; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoCipher { + + private PythonCryptoCipher() { + // private + } + + private static final IDetectionRule ENCRYPT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("encrypt") + .shouldBeDetectedAs(new CipherActionFactory<>(CipherAction.Action.ENCRYPT)) + .withMethodParameter(ANY) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule DECRYPT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("decrypt") + .shouldBeDetectedAs(new CipherActionFactory<>(CipherAction.Action.DECRYPT)) + .withMethodParameter(ANY) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule AES_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.AES") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("AES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.AES.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule AES_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.AES") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("AES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.AES.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule DES_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.DES") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("DES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.DES.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule DES_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.DES") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("DES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.DES.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule DES3_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.DES3") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("3DES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.DES3.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule DES3_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.DES3") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("3DES")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.DES3.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule BLOWFISH_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.Blowfish") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("Blowfish")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.Blowfish.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule BLOWFISH_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.Blowfish") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("Blowfish")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.Blowfish.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule CAST_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.CAST") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("CAST5")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.CAST.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule CAST_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.CAST") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("CAST5")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.CAST.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule ARC2_2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.ARC2") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("RC2")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.ARC2.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule ARC2_3 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.ARC2") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("RC2")) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Cipher.ARC2.*") + .shouldBeDetectedAs(new ModeFactory<>()) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // optional iv + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule ARC4 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.ARC4") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("RC4")) + .withAnyParameters() + .buildForContext(new CipherContext(Map.of("algorithm", "RC4"))) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule CHACHA20 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.ChaCha20") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("ChaCha20")) + .withAnyParameters() + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule CHACHA20_POLY1305 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.ChaCha20_Poly1305") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("ChaCha20Poly1305")) + .withAnyParameters() + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule SALSA20 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Cipher.Salsa20") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("Salsa20")) + .withAnyParameters() + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule PKCS1_OAEP = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectExactTypes("Crypto.Cipher.PKCS1_OAEP") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("PKCS1_OAEP")) + .withAnyParameters() // This must be changed if the rule below is enabled. + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + // // Variant with hash algo. This detects the hash but it won't be mapped. + // private static final IDetectionRule PKCS1_OAEP_NEW_WITH_HASH = + // new DetectionRuleBuilder() + // .createDetectionRule() + // .forObjectExactTypes("Crypto.Cipher.PKCS1_OAEP") + // .forMethods("new") + // .shouldBeDetectedAs(new ValueActionFactory<>("PKCS1_OAEP")) + // .withMethodParameter(ANY) // key + // .withMethodParameter("Crypto.Hash.*") + // .shouldBeDetectedAs(new AlgorithmFactory<>()) + // .asChildOfParameterWithId(-1) + // .buildForContext(new CipherContext()) + // .inBundle(() -> "PyCrypto") + // .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule PKCS1_V1_5 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectExactTypes("Crypto.Cipher.PKCS1_v1_5") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("PKCS1_v1_5")) + .withAnyParameters() + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(ENCRYPT, DECRYPT)); + + private static final IDetectionRule SEAL = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("seal") + .shouldBeDetectedAs(new CipherActionFactory<>(CipherAction.Action.ENCRYPT)) + .withMethodParameter(ANY) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule UNSEAL = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("unseal") + .shouldBeDetectedAs(new CipherActionFactory<>(CipherAction.Action.DECRYPT)) + .withMethodParameter(ANY) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule HPKE = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectExactTypes("Crypto.Protocol.HPKE") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("HPKE")) + .withMethodParameter(ANY) + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.ECCRules()) + .withMethodParameter("Crypto.Protocol.HPKE.AEAD.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new CipherContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SEAL, UNSEAL)); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoCipher::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of( + AES_2, + AES_3, + DES_2, + DES_3, + DES3_2, + DES3_3, + BLOWFISH_2, + BLOWFISH_3, + CAST_2, + CAST_3, + ARC2_2, + ARC2_3, + ARC4, + CHACHA20, + CHACHA20_POLY1305, + SALSA20, + PKCS1_OAEP, + // PKCS1_OAEP_NEW_WITH_HASH, + PKCS1_V1_5, + HPKE); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/hash/PythonCryptoHash.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/hash/PythonCryptoHash.java new file mode 100644 index 000000000..324808bd2 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/hash/PythonCryptoHash.java @@ -0,0 +1,96 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import com.ibm.engine.model.context.DigestContext; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoHash { + + private PythonCryptoHash() { + // private + } + + public static final List hashes = + Arrays.asList( + "MD2", + "MD4", + "MD5", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3_224", + "SHA3_256", + "SHA3_384", + "SHA3_512", + "RIPEMD160", + "keccak", + "TupleHash128", + "TupleHash256", + "SHAKE128", + "SHAKE256", + "cSHAKE128", + "cSHAKE256", + "KMAC128", + "KMAC256", + "KangarooTwelve", + "Poly1305", + "BLAKE2b", + "BLAKE2s"); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoHash::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + LinkedList> rules = new LinkedList<>(); + for (final String hash : PythonCryptoHash.hashes) { + rules.add( + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Hash." + hash) + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>(hash)) + .withAnyParameters() + .buildForContext(new DigestContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules()); + } + return rules; + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PythonCryptoKDF.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PythonCryptoKDF.java new file mode 100644 index 000000000..091d48cae --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PythonCryptoKDF.java @@ -0,0 +1,175 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static com.ibm.engine.detection.MethodMatcher.ANY; + +import com.ibm.engine.model.AlgorithmParameter; +import com.ibm.engine.model.Size; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.engine.model.factory.AlgorithmFactory; +import com.ibm.engine.model.factory.AlgorithmParameterFactory; +import com.ibm.engine.model.factory.KeySizeFactory; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoKDF { + + private PythonCryptoKDF() { + // private + } + + // PBKDF1 - module function call + private static final IDetectionRule PBKDF1 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("PBKDF1") + .shouldBeDetectedAs(new ValueActionFactory<>("PBKDF1")) + .withMethodParameter(ANY) // password + .withMethodParameter(ANY) // salt + .withMethodParameter("int") // dkLen + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(-1) + .withMethodParameter("int") // count + .shouldBeDetectedAs( + new AlgorithmParameterFactory<>(AlgorithmParameter.Kind.ITERATIONS)) + .asChildOfParameterWithId(-1) + .withMethodParameter("Crypto.Hash.*") // hashAlgo + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext( + new KeyDerivationFunctionContext(Map.of("kind", "pycrypto-pbkdf1"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + // PBKDF2 - module function call + private static final IDetectionRule PBKDF2 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("PBKDF2") + .shouldBeDetectedAs(new ValueActionFactory<>("PBKDF2")) + .withMethodParameter(ANY) // password + .withMethodParameter(ANY) // salt + .withMethodParameter("int") // dkLen + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(-1) + .withMethodParameter("int") // count + .shouldBeDetectedAs( + new AlgorithmParameterFactory<>(AlgorithmParameter.Kind.ITERATIONS)) + .withMethodParameter("Crypto.Hash.*") // hashAlgo + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext( + new KeyDerivationFunctionContext(Map.of("kind", "pycrypto-pbkdf2"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + // scrypt - module function call + private static final IDetectionRule SCRYPT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("scrypt") + .shouldBeDetectedAs(new ValueActionFactory<>("scrypt")) + .withMethodParameter(ANY) // password + .withMethodParameter(ANY) // salt + .withMethodParameter("int") // key_len + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(-1) + .withMethodParameter("int") // N + .withMethodParameter("int") // r + .withMethodParameter("int") // p + .withMethodParameter("int") // num_keys + .buildForContext(new KeyDerivationFunctionContext(Map.of("kind", "scrypt"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + // bcrypt - module function call + private static final IDetectionRule BCRYPT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("bcrypt") + .shouldBeDetectedAs(new ValueActionFactory<>("bcrypt")) + .withMethodParameter(ANY) // password + .withMethodParameter("int") // cost + .shouldBeDetectedAs( + new AlgorithmParameterFactory<>(AlgorithmParameter.Kind.ITERATIONS)) + .withMethodParameter(ANY) // salt + .buildForContext(new KeyDerivationFunctionContext(Map.of("kind", "bcrypt"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + // bcrypt_check - module function call + private static final IDetectionRule BCRYPT_CHECK = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("bcrypt_check") + .shouldBeDetectedAs(new ValueActionFactory<>("bcrypt")) + .withMethodParameter(ANY) // password + .withMethodParameter(ANY) // bcrypt_hash + .buildForContext(new KeyDerivationFunctionContext(Map.of("kind", "bcrypt"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + private static final IDetectionRule HKDF = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.KDF") + .forMethods("HKDF") + .shouldBeDetectedAs(new ValueActionFactory<>("HKDF")) + .withMethodParameter(ANY) // master + .withMethodParameter("int") // keylen + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BYTE)) + .asChildOfParameterWithId(-1) + .withMethodParameter(ANY) // salt + .withMethodParameter("Crypto.Hash.*") // hash_mod + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext( + new KeyDerivationFunctionContext(Map.of("kind", "pycrypto-hkdf"))) + .inBundle(() -> "PyCa") + .withoutDependingDetectionRules(); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoKDF::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of(PBKDF1, PBKDF2, SCRYPT, BCRYPT, BCRYPT_CHECK, HKDF); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/PythonCryptoKeyAgreement.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/PythonCryptoKeyAgreement.java new file mode 100644 index 000000000..fce667513 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/PythonCryptoKeyAgreement.java @@ -0,0 +1,116 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.engine.model.factory.KeyActionFactory; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoKeyAgreement { + + private PythonCryptoKeyAgreement() { + // private + } + + // DH.key_agreement - module function call + private static final IDetectionRule DH_KEY_AGREEMENT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.DH") + .forMethods("key_agreement") + .shouldBeDetectedAs(new ValueActionFactory<>("ECDH")) + .withAnyParameters() + .buildForContext(new KeyAgreementContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule IMPORT_X25519_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.DH") + .forMethods("import_x25519_public_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyAgreementContext(Map.of("algorithm", "x25519"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule IMPORT_X25519_PRIVATE_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.DH") + .forMethods("import_x25519_private_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyAgreementContext(Map.of("algorithm", "x25519"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule IMPORT_X448_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.DH") + .forMethods("import_x448_public_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyAgreementContext(Map.of("algorithm", "x448"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule IMPORT_X448_PRIVATE_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Protocol.DH") + .forMethods("import_x448_private_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyAgreementContext(Map.of("algorithm", "x448"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoKeyAgreement::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of( + DH_KEY_AGREEMENT, + IMPORT_X25519_PUBLIC_KEY, + IMPORT_X25519_PRIVATE_KEY, + IMPORT_X448_PUBLIC_KEY, + IMPORT_X448_PRIVATE_KEY); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/mac/PythonCryptoMac.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/mac/PythonCryptoMac.java new file mode 100644 index 000000000..c16d54138 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/mac/PythonCryptoMac.java @@ -0,0 +1,93 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.mac; + +import static com.ibm.engine.detection.MethodMatcher.ANY; + +import com.ibm.engine.model.context.MacContext; +import com.ibm.engine.model.factory.AlgorithmFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoMac { + + private PythonCryptoMac() { + // private + } + + private static final IDetectionRule NEW_CMAC = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Hash.CMAC") + .forMethods("new") + .withMethodParameter(ANY) // key + .withMethodParameter("Crypto.Cipher.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .buildForContext(new MacContext(Map.of("kind", "cmac"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule NEW_HMAC = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Hash.HMAC") + .forMethods("new") + .withMethodParameter(ANY) // secret + .withMethodParameter("Crypto.Hash.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .buildForContext(new MacContext(Map.of("kind", "hmac"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // Crypto Poly1305 is the old algorithm that requires a cipher parameter. + // Our Poly1305 class represents the modern IETF standard (RFC 7539 / RFC 8439). + // private static final IDetectionRule NEW_POLY1305 = + // new DetectionRuleBuilder() + // .createDetectionRule() + // .forObjectTypes("Crypto.Hash.Poly1305") + // .forMethods("new") + // .withMethodParameter(ANY) // key + // .withMethodParameter("Crypto.Cipher.*") + // .shouldBeDetectedAs(new AlgorithmFactory<>()) + // .buildForContext(new MacContext(Map.of("kind", "poly1305"))) + // .inBundle(() -> "PyCrypto") + // .withoutDependingDetectionRules(); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoMac::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of(NEW_CMAC, NEW_HMAC); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/publickey/PythonCryptoPublicKey.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/publickey/PythonCryptoPublicKey.java new file mode 100644 index 000000000..e1fdb9483 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/publickey/PythonCryptoPublicKey.java @@ -0,0 +1,297 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.publickey; + +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.Size; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.engine.model.context.PublicKeyContext; +import com.ibm.engine.model.factory.CurveFactory; +import com.ibm.engine.model.factory.KeyActionFactory; +import com.ibm.engine.model.factory.KeySizeFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoPublicKey { + + private PythonCryptoPublicKey() { + // private + } + + // RSA generate -> private key + private static final IDetectionRule RSA_GENERATE = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.RSA") + .forMethods("generate") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PRIVATE_KEY_GENERATION)) + .withMethodParameter("int") // keylen + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .asChildOfParameterWithId(-1) + .buildForContext(new PrivateKeyContext(Map.of("algorithm", "RSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // RSA construct and import_key -> public or private key + private static final IDetectionRule RSA_CONSTRUCT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.RSA") + .forMethods("construct", "import_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyContext(Map.of("algorithm", "RSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // RsaKey public_key -> public key + private static final IDetectionRule RSA_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.RSA.RsaKey") + .forMethods("public_key") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PUBLIC_KEY_GENERATION)) + .withoutParameters() + .buildForContext(new PublicKeyContext(Map.of("algorithm", "RSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // DSA generate -> private key + private static final IDetectionRule DSA_GENERATE = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.DSA") + .forMethods("generate") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PRIVATE_KEY_GENERATION)) + .withMethodParameter("int") // keylen + .shouldBeDetectedAs(new KeySizeFactory<>(Size.UnitType.BIT)) + .asChildOfParameterWithId(-1) + .buildForContext(new PrivateKeyContext(Map.of("algorithm", "DSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // DSA construct and import_key -> public or private key + private static final IDetectionRule DSA_CONSTRUCT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.DSA") + .forMethods("construct", "import_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyContext(Map.of("algorithm", "DSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // DsaKey public_key -> public key + private static final IDetectionRule DSA_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.DSA.DsaKey") + .forMethods("public_key") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PUBLIC_KEY_GENERATION)) + .withoutParameters() + .buildForContext(new PublicKeyContext(Map.of("algorithm", "DSA"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // ECC key generation + private static final IDetectionRule ECC_GENERATE = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ECC") + .forMethods("generate") + // .shouldBeDetectedAs(new + // KeyActionFactory<>(KeyAction.Action.PRIVATE_KEY_GENERATION)) + .withMethodParameter("str") + .shouldBeDetectedAs(new CurveFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new PrivateKeyContext(Map.of("algorithm", "EC"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // ECC key construction + private static final IDetectionRule ECC_CONSTRUCT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ECC") + .forMethods("construct") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withMethodParameter("str") + .shouldBeDetectedAs(new CurveFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new KeyContext(Map.of("algorithm", "EC"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // ECC import + private static final IDetectionRule ECC_IMPORT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ECC") + .forMethods("import_key") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyContext(Map.of("algorithm", "EC_IMPORT"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // EccKey public_key -> public key + private static final IDetectionRule ECC_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ECC.EccKey") + .forMethods("public_key") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PUBLIC_KEY_GENERATION)) + .withoutParameters() + .buildForContext(new PublicKeyContext(Map.of("algorithm", "ECC"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // EdDSA import private key + private static final IDetectionRule EDDSA_IMPORT_PRIVATE_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.eddsa") + .forMethods("import_private_key") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PRIVATE_KEY_GENERATION)) + .withAnyParameters() + .buildForContext(new PrivateKeyContext(Map.of("algorithm", "ECC"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // EdDSA import public key + private static final IDetectionRule EDDSA_IMPORT_PUBLIC_KEY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.eddsa") + .forMethods("import_public_key") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PUBLIC_KEY_GENERATION)) + .withAnyParameters() + .buildForContext(new PublicKeyContext(Map.of("algorithm", "ECC"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // ElGamal + private static final IDetectionRule ELGAMAL_GENERATE = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ElGamal") + .forMethods("generate") + .shouldBeDetectedAs( + new KeyActionFactory<>(KeyAction.Action.PRIVATE_KEY_GENERATION)) + .withAnyParameters() + .buildForContext(new PrivateKeyContext(Map.of("algorithm", "ElGamal"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // ElGamal + private static final IDetectionRule ELGAMAL_CONSTRUCT = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.PublicKey.ElGamal") + .forMethods("construct") + .shouldBeDetectedAs(new KeyActionFactory<>(KeyAction.Action.GENERATION)) + .withAnyParameters() + .buildForContext(new KeyContext(Map.of("algorithm", "ElGamal"))) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + @Nonnull + private static final Supplier>> RSA_RULES = + Memoize.of(PythonCryptoPublicKey::buildRSARules); + + @Nonnull + public static List> RSARules() { + return RSA_RULES.get(); + } + + @Nonnull + private static List> buildRSARules() { + return List.of(RSA_CONSTRUCT, RSA_GENERATE, RSA_PUBLIC_KEY); + } + + @Nonnull + private static final Supplier>> DSA_RULES = + Memoize.of(PythonCryptoPublicKey::buildDSARules); + + @Nonnull + public static List> DSARules() { + return DSA_RULES.get(); + } + + @Nonnull + private static List> buildDSARules() { + return List.of(DSA_CONSTRUCT, DSA_GENERATE, DSA_PUBLIC_KEY); + } + + @Nonnull + private static final Supplier>> ECC_RULES = + Memoize.of(PythonCryptoPublicKey::buildECCRules); + + @Nonnull + public static List> ECCRules() { + return ECC_RULES.get(); + } + + @Nonnull + private static List> buildECCRules() { + return List.of(ECC_CONSTRUCT, ECC_GENERATE, ECC_IMPORT, ECC_PUBLIC_KEY); + } + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoPublicKey::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of( + RSA_CONSTRUCT, + RSA_GENERATE, + DSA_CONSTRUCT, + DSA_GENERATE, + ECC_CONSTRUCT, + ECC_GENERATE, + ECC_IMPORT, + EDDSA_IMPORT_PRIVATE_KEY, + EDDSA_IMPORT_PUBLIC_KEY, + ELGAMAL_CONSTRUCT, + ELGAMAL_GENERATE); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/random/PythonCryptoRandom.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/random/PythonCryptoRandom.java new file mode 100644 index 000000000..3e2529696 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/random/PythonCryptoRandom.java @@ -0,0 +1,77 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.random; + +import static com.ibm.engine.detection.MethodMatcher.ANY; + +import com.ibm.engine.model.context.PRNGContext; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import java.util.List; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoRandom { + + private PythonCryptoRandom() { + // private + } + + private static final IDetectionRule RANDOM_GET_BYTES = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Random") + .forMethods("get_random_bytes") + .shouldBeDetectedAs(new ValueActionFactory<>("PRNG")) + .withMethodParameter(ANY) + .buildForContext(new PRNGContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule RANDOM_FUNC = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Random.random") + .forMethods( + "getrandbits", "randrange", "randint", "choice", "shuflle", "sample") + .shouldBeDetectedAs(new ValueActionFactory<>("PRNG")) + .withMethodParameter(ANY) + .buildForContext(new PRNGContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoRandom::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of(RANDOM_GET_BYTES, RANDOM_FUNC); + } +} diff --git a/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/signature/PythonCryptoSignature.java b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/signature/PythonCryptoSignature.java new file mode 100644 index 000000000..e1b757694 --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/rules/detection/pycrypto/signature/PythonCryptoSignature.java @@ -0,0 +1,182 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static com.ibm.engine.detection.MethodMatcher.ANY; + +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.engine.model.factory.AlgorithmFactory; +import com.ibm.engine.model.factory.SignatureActionFactory; +import com.ibm.engine.model.factory.ValueActionFactory; +import com.ibm.engine.rule.IDetectionRule; +import com.ibm.engine.rule.builder.DetectionRuleBuilder; +import com.ibm.plugin.rules.detection.Memoize; +import com.ibm.plugin.rules.detection.pycrypto.hash.PythonCryptoHash; +import com.ibm.plugin.rules.detection.pycrypto.publickey.PythonCryptoPublicKey; +import java.util.List; +import java.util.function.Supplier; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1192") +public final class PythonCryptoSignature { + + private PythonCryptoSignature() { + // private + } + + private static final IDetectionRule SIGN = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("sign") + .shouldBeDetectedAs(new SignatureActionFactory<>(SignatureAction.Action.SIGN)) + .withMethodParameter("Crypto.Hash.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoHash.rules()) + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + private static final IDetectionRule VERIFY = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes(ANY) + .forMethods("verify") + .shouldBeDetectedAs(new SignatureActionFactory<>(SignatureAction.Action.VERIFY)) + .withMethodParameter("Crypto.Hash.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoHash.rules()) + .withMethodParameter(ANY) // the signature to be verified + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withoutDependingDetectionRules(); + + // PSS signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule PKCS1V15 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.pkcs1_15") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("RSA")) + .withMethodParameter("Crypto.PublicKey.RSA") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.RSARules()) + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + // PSS signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule PSS = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.pss") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("RSA-PSS")) + .withMethodParameter("Crypto.PublicKey.RSA") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.RSARules()) + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + // PSS signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule PSS_MGF1 = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.pss") + .forMethods("MGF1") + .shouldBeDetectedAs(new ValueActionFactory<>("MGF1")) + .withMethodParameter(ANY) + .withMethodParameter(ANY) + .withMethodParameter("Crypto.Hash.*") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + // DSS signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule DSS = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.DSS") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("DSS")) + .withMethodParameter("Crypto.PublicKey.DSA") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.DSARules()) + .withMethodParameter(ANY) // the mode parameter + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + // DSS signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule ECDSA = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.DSS") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("ECDSA")) + .withMethodParameter("Crypto.PublicKey.ECC") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.ECCRules()) + .withMethodParameter(ANY) // the mode parameter + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + // EdDSA signature scheme - sign and verify methods (called on the result of .new()) + private static final IDetectionRule EDDSA = + new DetectionRuleBuilder() + .createDetectionRule() + .forObjectTypes("Crypto.Signature.eddsa") + .forMethods("new") + .shouldBeDetectedAs(new ValueActionFactory<>("EDDSA")) + .withMethodParameter("Crypto.PublicKey.ECC") + .shouldBeDetectedAs(new AlgorithmFactory<>()) + .asChildOfParameterWithId(-1) + .addDependingDetectionRules(PythonCryptoPublicKey.ECCRules()) + .withMethodParameter(ANY) // the mode parameter + .buildForContext(new SignatureContext()) + .inBundle(() -> "PyCrypto") + .withDependingDetectionRules(List.of(SIGN, VERIFY)); + + @Nonnull + private static final Supplier>> RULES = + Memoize.of(PythonCryptoSignature::buildRules); + + @Nonnull + public static List> rules() { + return RULES.get(); + } + + @Nonnull + private static List> buildRules() { + return List.of(PKCS1V15, PSS, PSS_MGF1, DSS, ECDSA, EDDSA); + } +} diff --git a/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java b/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java index 6bb880f0e..ca3155eb1 100644 --- a/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java +++ b/python/src/main/java/com/ibm/plugin/translation/reorganizer/PythonReorganizerRules.java @@ -21,9 +21,11 @@ import com.ibm.mapper.model.BlockCipher; import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.ProbabilisticSignatureScheme; import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.Signature; import com.ibm.mapper.model.functionality.Sign; +import com.ibm.mapper.model.functionality.Verify; import com.ibm.mapper.reorganizer.IReorganizerRule; import com.ibm.mapper.reorganizer.rules.KeyAgreementReorganizer; import com.ibm.mapper.reorganizer.rules.KeyDerivationReorganizer; @@ -42,6 +44,14 @@ private PythonReorganizerRules() { @Nonnull public static List rules() { return Stream.of( + SignatureReorganizer.moveNodesFromUnderFunctionalityUnderParent( + Verify.class, ProbabilisticSignatureScheme.class), + SignatureReorganizer.moveNodesFromUnderFunctionalityUnderParent( + Verify.class, Signature.class), + SignatureReorganizer.moveNodesFromUnderFunctionalityUnderParent( + Sign.class, ProbabilisticSignatureScheme.class), + SignatureReorganizer.moveNodesFromUnderFunctionalityUnderParent( + Sign.class, Signature.class), SignatureReorganizer.moveNodesFromUnderFunctionalityUnderNode( Sign.class, PublicKeyEncryption.class), SignatureReorganizer.moveNodesFromUnderFunctionalityUnderNode( diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/PythonTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/PythonTranslator.java index 4a22bb4a2..a349601c3 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/PythonTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/PythonTranslator.java @@ -27,6 +27,7 @@ import com.ibm.engine.model.context.KeyContext; import com.ibm.engine.model.context.KeyDerivationFunctionContext; import com.ibm.engine.model.context.MacContext; +import com.ibm.engine.model.context.PRNGContext; import com.ibm.engine.model.context.PrivateKeyContext; import com.ibm.engine.model.context.PublicKeyContext; import com.ibm.engine.model.context.SecretKeyContext; @@ -38,11 +39,12 @@ import com.ibm.plugin.translation.translator.contexts.PycaCipherContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaDigestContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaKeyAgreementContextTranslator; +import com.ibm.plugin.translation.translator.contexts.PycaKeyContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaKeyDerivationContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaMacContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaPrivateKeyContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaPublicKeyContextTranslator; -import com.ibm.plugin.translation.translator.contexts.PycaSecretContextTranslator; +import com.ibm.plugin.translation.translator.contexts.PycaRandomContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaSecretKeyContextTranslator; import com.ibm.plugin.translation.translator.contexts.PycaSignatureContextTranslator; import java.util.List; @@ -86,11 +88,6 @@ public Optional translate( new PycaKeyDerivationContextTranslator(); return pycaKeyDerivationContextTranslator.translate( bundleIdentifier, value, detectionValueContext, detectionLocation); - } else if (detectionValueContext.is(KeyContext.class)) { - final PycaSecretContextTranslator pycaSecretContextTranslator = - new PycaSecretContextTranslator(); - return pycaSecretContextTranslator.translate( - bundleIdentifier, value, detectionValueContext, detectionLocation); } else if (detectionValueContext.is(PrivateKeyContext.class)) { final PycaPrivateKeyContextTranslator pycaPrivateKeyContextTranslator = new PycaPrivateKeyContextTranslator(); @@ -106,6 +103,11 @@ public Optional translate( new PycaPublicKeyContextTranslator(); return pycaPublicKeyContextTranslator.translate( bundleIdentifier, value, detectionValueContext, detectionLocation); + } else if (detectionValueContext.is(KeyContext.class)) { + final PycaKeyContextTranslator pycaKeyContextTranslator = + new PycaKeyContextTranslator(); + return pycaKeyContextTranslator.translate( + bundleIdentifier, value, detectionValueContext, detectionLocation); } else if (detectionValueContext.is(DigestContext.class)) { final PycaDigestContextTranslator pycaDigestContextTranslator = new PycaDigestContextTranslator(); @@ -126,6 +128,11 @@ public Optional translate( new PycaMacContextTranslator(); return pycaMacContextTranslator.translate( bundleIdentifier, value, detectionValueContext, detectionLocation); + } else if (detectionValueContext.is(PRNGContext.class)) { + final PycaRandomContextTranslator pycaRandomContextTranslator = + new PycaRandomContextTranslator(); + return pycaRandomContextTranslator.translate( + bundleIdentifier, value, detectionValueContext, detectionLocation); } return Optional.empty(); } diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaCipherContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaCipherContextTranslator.java index eec44d2aa..5a961e63f 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaCipherContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaCipherContextTranslator.java @@ -19,6 +19,7 @@ */ package com.ibm.plugin.translation.translator.contexts; +import com.ibm.engine.model.Algorithm; import com.ibm.engine.model.CipherAction; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeySize; @@ -30,10 +31,13 @@ import com.ibm.mapper.IContextTranslation; import com.ibm.mapper.mapper.pyca.PycaCipherMapper; import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyLength; import com.ibm.mapper.model.KeyWrap; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.algorithms.AES; +import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.functionality.Decrypt; import com.ibm.mapper.model.functionality.Encapsulate; import com.ibm.mapper.model.functionality.Encrypt; @@ -41,15 +45,19 @@ import com.ibm.mapper.model.mode.CCM; import com.ibm.mapper.model.mode.CFB; import com.ibm.mapper.model.mode.CTR; +import com.ibm.mapper.model.mode.EAX; import com.ibm.mapper.model.mode.ECB; import com.ibm.mapper.model.mode.GCM; import com.ibm.mapper.model.mode.GCMSIV; +import com.ibm.mapper.model.mode.KW; +import com.ibm.mapper.model.mode.KWP; import com.ibm.mapper.model.mode.OCB; import com.ibm.mapper.model.mode.OFB; import com.ibm.mapper.model.mode.SIV; import com.ibm.mapper.model.mode.XTS; import com.ibm.mapper.model.padding.ANSIX923; import com.ibm.mapper.model.padding.OAEP; +import com.ibm.mapper.model.padding.PKCS1; import com.ibm.mapper.model.padding.PKCS7; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; @@ -66,7 +74,7 @@ public final class PycaCipherContextTranslator implements IContextTranslation + if (value instanceof Algorithm && detectionContext instanceof DetectionContext context) { if (context.get("kind").map(k -> k.equals("AEAD")).orElse(false)) { return switch (value.asString().toUpperCase().trim()) { @@ -85,25 +93,49 @@ public final class PycaCipherContextTranslator implements IContextTranslation i); } else if (value instanceof ValueAction - && detectionContext instanceof DetectionContext context - && context.get("kind").map(k -> k.equals("padding")).orElse(false) // padding case - ) { - return switch (value.asString().toUpperCase().trim()) { - case "PKCS7" -> Optional.of(new PKCS7(detectionLocation)); - case "ANSIX923" -> Optional.of(new ANSIX923(detectionLocation)); - case "OAEP" -> Optional.of(new OAEP(detectionLocation)); - default -> Optional.empty(); + && detectionContext instanceof DetectionContext context) { + if (context.get("kind").map(k -> k.equals("padding")).orElse(false)) { // padding case + return switch (value.asString().toUpperCase().trim()) { + case "PKCS7" -> Optional.of(new PKCS7(detectionLocation)); + case "ANSIX923" -> Optional.of(new ANSIX923(detectionLocation)); + case "OAEP" -> Optional.of(new OAEP(detectionLocation)); + default -> Optional.empty(); + }; + } + + // Handle ValueAction with algorithm name (e.g., "AES", "DES", "DES3") + // Get the algorithm name from the ValueAction + String algorithmName = value.asString(); + return switch (algorithmName) { + case "PKCS1_OAEP" -> { + RSA rsaOaep = new RSA(PublicKeyEncryption.class, detectionLocation); + rsaOaep.put(new OAEP(detectionLocation)); + yield Optional.of((INode) rsaOaep); + } + case "PKCS1_v1_5" -> { + RSA rsaPkcs1 = new RSA(PublicKeyEncryption.class, detectionLocation); + rsaPkcs1.put(new PKCS1(detectionLocation)); + yield Optional.of((INode) rsaPkcs1); + } + case "HPKE" -> Optional.of(new EllipticCurveAlgorithm(detectionLocation)); + default -> pycaCipherMapper.parse(algorithmName, detectionLocation).map(i -> i); }; } else if (value instanceof Mode mode) { return switch (mode.asString().toUpperCase().trim()) { - case "CBC" -> Optional.of(new CBC(detectionLocation)); - case "CTR" -> Optional.of(new CTR(detectionLocation)); - case "OFB" -> Optional.of(new OFB(detectionLocation)); - case "CFB" -> Optional.of(new CFB(detectionLocation)); + case "CBC", "MODE_CBC" -> Optional.of(new CBC(detectionLocation)); + case "CTR", "MODE_CTR" -> Optional.of(new CTR(detectionLocation)); + case "OFB", "MODE_OFB" -> Optional.of(new OFB(detectionLocation)); + case "MODE_OCB" -> Optional.of(new OCB(detectionLocation)); + case "CFB", "MODE_CFB" -> Optional.of(new CFB(detectionLocation)); case "CFB8" -> Optional.of(new CFB(8, detectionLocation)); - case "GCM" -> Optional.of(new GCM(detectionLocation)); + case "GCM", "MODE_GCM" -> Optional.of(new GCM(detectionLocation)); case "XTS" -> Optional.of(new XTS(detectionLocation)); - case "ECB" -> Optional.of(new ECB(detectionLocation)); + case "ECB", "MODE_ECB" -> Optional.of(new ECB(detectionLocation)); + case "MODE_EAX" -> Optional.of(new EAX(detectionLocation)); + case "CCM", "MODE_CCM" -> Optional.of(new CCM(detectionLocation)); + case "MODE_SIV" -> Optional.of(new SIV(detectionLocation)); + case "MODE_KW" -> Optional.of(new KW(detectionLocation)); + case "MODE_KWP" -> Optional.of(new KWP(detectionLocation)); default -> Optional.empty(); }; } else if (value instanceof CipherAction cipherAction diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java index face8bc21..6333c5cc8 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaDigestContextTranslator.java @@ -19,6 +19,7 @@ */ package com.ibm.plugin.translation.translator.contexts; +import com.ibm.engine.model.Algorithm; import com.ibm.engine.model.IValue; import com.ibm.engine.model.ValueAction; import com.ibm.engine.model.context.IDetectionContext; @@ -41,7 +42,7 @@ public final class PycaDigestContextTranslator implements IContextTranslation value, @Nonnull IDetectionContext detectionContext, @Nonnull DetectionLocation detectionLocation) { - if (value instanceof ValueAction || value instanceof com.ibm.engine.model.Algorithm) { + if (value instanceof ValueAction || value instanceof Algorithm) { final PycaDigestMapper pycaDigestMapper = new PycaDigestMapper(); return pycaDigestMapper .parse(value.asString(), detectionLocation) diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java index 89b68213b..4362d2370 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyAgreementContextTranslator.java @@ -22,6 +22,7 @@ import com.ibm.engine.model.Algorithm; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.ValueAction; import com.ibm.engine.model.context.DetectionContext; import com.ibm.engine.model.context.IDetectionContext; import com.ibm.engine.rule.IBundle; @@ -46,11 +47,11 @@ public class PycaKeyAgreementContextTranslator implements IContextTranslation value, @Nonnull IDetectionContext detectionContext, @Nonnull DetectionLocation detectionLocation) { - if (value instanceof Algorithm algorithm) { - return Optional.of(algorithm) + if (value instanceof ValueAction || value instanceof Algorithm) { + return Optional.of(value.asString().toUpperCase().trim()) .map( algo -> - switch (algo.asString().toUpperCase().trim()) { + switch (algo) { case "ECDH" -> new ECDH(detectionLocation); case "EC" -> new EllipticCurveAlgorithm( diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyContextTranslator.java new file mode 100644 index 000000000..43e24c78c --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyContextTranslator.java @@ -0,0 +1,89 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import com.ibm.engine.model.Curve; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.DetectionContext; +import com.ibm.engine.model.context.IDetectionContext; +import com.ibm.engine.rule.IBundle; +import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.mapper.pyca.PycaCurveMapper; +import com.ibm.mapper.model.EllipticCurveAlgorithm; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.algorithms.DSA; +import com.ibm.mapper.model.algorithms.ElGamal; +import com.ibm.mapper.model.algorithms.Fernet; +import com.ibm.mapper.model.algorithms.RSA; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +public final class PycaKeyContextTranslator implements IContextTranslation { + @Override + public @Nonnull Optional translate( + @Nonnull IBundle bundleIdentifier, + @Nonnull IValue value, + @Nonnull IDetectionContext detectionContext, + @Nonnull DetectionLocation detectionLocation) { + if (value instanceof KeyAction + && detectionContext instanceof DetectionContext context) { + // action is always "generate" + return context.get("algorithm") + .map( + str -> + switch (str.toUpperCase().trim()) { + case "RSA" -> new RSA(detectionLocation); + case "DSA" -> new DSA(detectionLocation); + case "EC_IMPORT" -> + new EllipticCurveAlgorithm(detectionLocation); + case "ELGAMAL" -> new ElGamal(detectionLocation); + case "FERNET" -> new Fernet(detectionLocation); + default -> null; + }) + .map( + algo -> { + final Key key = new Key(algo); + key.put(new KeyGeneration(detectionLocation)); + return key; + }); + } else if (value instanceof Curve curve + && detectionContext instanceof DetectionContext context + && context.get("algorithm").map(a -> a.equalsIgnoreCase("EC")).orElse(false)) { + final PycaCurveMapper mapper = new PycaCurveMapper(); + return mapper.parse(curve.asString(), detectionLocation) + .map( + ec -> { + Key key = new Key((PublicKeyEncryption) ec); + key.put(new KeyGeneration(detectionLocation)); + // currently only GENERATE is + // used as key action is this + // context + return key; + }); + } + return Optional.empty(); + } +} diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java index 72ed5115d..1ddc88217 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaKeyDerivationContextTranslator.java @@ -21,8 +21,10 @@ import com.ibm.engine.model.Algorithm; import com.ibm.engine.model.IValue; +import com.ibm.engine.model.IterationCount; import com.ibm.engine.model.KeySize; import com.ibm.engine.model.Mode; +import com.ibm.engine.model.SaltSize; import com.ibm.engine.model.ValueAction; import com.ibm.engine.model.context.DetectionContext; import com.ibm.engine.model.context.IDetectionContext; @@ -33,11 +35,14 @@ import com.ibm.mapper.model.Cipher; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.NumberOfIterations; +import com.ibm.mapper.model.SaltLength; import com.ibm.mapper.model.algorithms.ANSIX963; import com.ibm.mapper.model.algorithms.CMAC; import com.ibm.mapper.model.algorithms.ConcatenationKDF; import com.ibm.mapper.model.algorithms.HKDF; import com.ibm.mapper.model.algorithms.HMAC; +import com.ibm.mapper.model.algorithms.PBKDF1; import com.ibm.mapper.model.algorithms.PBKDF2; import com.ibm.mapper.model.algorithms.Scrypt; import com.ibm.mapper.model.functionality.KeyDerivation; @@ -101,6 +106,17 @@ public class PycaKeyDerivationContextTranslator implements IContextTranslation { + final PycaDigestMapper digestMapper = new PycaDigestMapper(); + yield digestMapper + .parse(algorithm.asString(), detectionLocation) + .map( + kdf -> { + final PBKDF1 pbkdf1 = new PBKDF1(kdf); + pbkdf1.put(new KeyDerivation(detectionLocation)); + return pbkdf1; + }); + } case "pbkdf2" -> { final PycaDigestMapper digestMapper = new PycaDigestMapper(); yield digestMapper @@ -112,6 +128,14 @@ public class PycaKeyDerivationContextTranslator implements IContextTranslation { + // ValueAction already creates the root KDF node for these rules; + // the Algorithm child should contribute only the digest. + final PycaDigestMapper digestMapper = new PycaDigestMapper(); + yield digestMapper + .parse(algorithm.asString(), detectionLocation) + .map(digest -> (INode) digest); + } case "concatkdf" -> { final PycaDigestMapper digestMapper = new PycaDigestMapper(); yield digestMapper @@ -146,11 +170,19 @@ public class PycaKeyDerivationContextTranslator implements IContextTranslation keySize) { return Optional.of(new KeyLength(keySize.getValue(), detectionLocation)); + } else if (value instanceof IterationCount iterationCount) { + return Optional.of( + new NumberOfIterations(iterationCount.getValue(), detectionLocation)); + } else if (value instanceof SaltSize saltSize) { + return Optional.of(new SaltLength(saltSize.getValue(), detectionLocation)); } else if (value instanceof ValueAction action) { return Optional.of(action.asString().toUpperCase().trim()) .map( str -> - switch (action.asString().toUpperCase().trim()) { + switch (str) { + case "PBKDF1" -> new PBKDF1(detectionLocation); + case "PBKDF2" -> new PBKDF2(detectionLocation); + case "HKDF" -> new HKDF(detectionLocation); case "SCRYPT" -> new Scrypt(detectionLocation); default -> null; }) diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaMacContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaMacContextTranslator.java index 8f9e14618..47940b9aa 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaMacContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaMacContextTranslator.java @@ -19,6 +19,7 @@ */ package com.ibm.plugin.translation.translator.contexts; +import com.ibm.engine.model.Algorithm; import com.ibm.engine.model.IValue; import com.ibm.engine.model.ValueAction; import com.ibm.engine.model.context.DetectionContext; @@ -47,7 +48,7 @@ public final class PycaMacContextTranslator implements IContextTranslation @Nonnull IDetectionContext detectionContext, @Nonnull DetectionLocation detectionLocation) { - if (value instanceof com.ibm.engine.model.Algorithm algorithm + if (value instanceof Algorithm algorithm && detectionContext instanceof DetectionContext context) { // hash algorithm Optional possibleKind = context.get("kind"); diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java index b82629bd7..8a3478df0 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPrivateKeyContextTranslator.java @@ -27,6 +27,7 @@ import com.ibm.engine.model.context.IDetectionContext; import com.ibm.engine.rule.IBundle; import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.mapper.pyca.PycaCurveMapper; import com.ibm.mapper.model.EllipticCurveAlgorithm; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.KeyLength; @@ -36,26 +37,8 @@ import com.ibm.mapper.model.algorithms.DSA; import com.ibm.mapper.model.algorithms.Ed25519; import com.ibm.mapper.model.algorithms.Ed448; +import com.ibm.mapper.model.algorithms.ElGamal; import com.ibm.mapper.model.algorithms.RSA; -import com.ibm.mapper.model.curves.Brainpoolp256r1; -import com.ibm.mapper.model.curves.Brainpoolp384r1; -import com.ibm.mapper.model.curves.Brainpoolp512r1; -import com.ibm.mapper.model.curves.Secp192r1; -import com.ibm.mapper.model.curves.Secp224r1; -import com.ibm.mapper.model.curves.Secp256k1; -import com.ibm.mapper.model.curves.Secp256r1; -import com.ibm.mapper.model.curves.Secp384r1; -import com.ibm.mapper.model.curves.Secp521r1; -import com.ibm.mapper.model.curves.Sect163k1; -import com.ibm.mapper.model.curves.Sect163r2; -import com.ibm.mapper.model.curves.Sect233k1; -import com.ibm.mapper.model.curves.Sect233r1; -import com.ibm.mapper.model.curves.Sect283k1; -import com.ibm.mapper.model.curves.Sect283r1; -import com.ibm.mapper.model.curves.Sect409k1; -import com.ibm.mapper.model.curves.Sect409r1; -import com.ibm.mapper.model.curves.Sect571k1; -import com.ibm.mapper.model.curves.Sect571r1; import com.ibm.mapper.model.functionality.KeyGeneration; import com.ibm.mapper.utils.DetectionLocation; import java.util.Optional; @@ -84,41 +67,13 @@ public final class PycaPrivateKeyContextTranslator implements IContextTranslatio } else if (value instanceof Curve curve && detectionContext instanceof DetectionContext context && context.get("algorithm").map(a -> a.equalsIgnoreCase("EC")).orElse(false)) { - return Optional.of(curve.asString()) - .map( - str -> - switch (str.toUpperCase().trim()) { - case "SECP256R1" -> new Secp256r1(detectionLocation); - case "SECP384R1" -> new Secp384r1(detectionLocation); - case "SECP521R1" -> new Secp521r1(detectionLocation); - case "SECP224R1" -> new Secp224r1(detectionLocation); - case "SECP192R1" -> new Secp192r1(detectionLocation); - case "SECP256K1" -> new Secp256k1(detectionLocation); - case "BRAINPOOLP256R1" -> - new Brainpoolp256r1(detectionLocation); - case "BRAINPOOLP384R1" -> - new Brainpoolp384r1(detectionLocation); - case "BRAINPOOLP512R1" -> - new Brainpoolp512r1(detectionLocation); - case "SECT571K1" -> new Sect571k1(detectionLocation); - case "SECT409K1" -> new Sect409k1(detectionLocation); - case "SECT283K1" -> new Sect283k1(detectionLocation); - case "SECT233K1" -> new Sect233k1(detectionLocation); - case "SECT163K1" -> new Sect163k1(detectionLocation); - case "SECT571R1" -> new Sect571r1(detectionLocation); - case "SECT409R1" -> new Sect409r1(detectionLocation); - case "SECT283R1" -> new Sect283r1(detectionLocation); - case "SECT233R1" -> new Sect233r1(detectionLocation); - case "SECT163R2" -> new Sect163r2(detectionLocation); - default -> null; - }) - .map(EllipticCurveAlgorithm::new) + final PycaCurveMapper mapper = new PycaCurveMapper(); + return mapper.parse(curve.asString(), detectionLocation) .map( ec -> { PrivateKey privateKey = new PrivateKey((PublicKeyEncryption) ec); - privateKey.put( - new KeyGeneration( - detectionLocation)); // currently only GENERATE is + privateKey.put(new KeyGeneration(detectionLocation)); + // currently only GENERATE is // used as key action is this // context return privateKey; @@ -141,14 +96,14 @@ public final class PycaPrivateKeyContextTranslator implements IContextTranslatio case "EC" -> new EllipticCurveAlgorithm(detectionLocation); case "ED25519" -> new Ed25519(detectionLocation); case "ED448" -> new Ed448(detectionLocation); + case "ELGAMAL" -> new ElGamal(detectionLocation); default -> null; }) .map( algorithm -> { PrivateKey privateKey = new PrivateKey(algorithm); - privateKey.put( - new KeyGeneration( - detectionLocation)); // currently only GENERATE is + privateKey.put(new KeyGeneration(detectionLocation)); + // currently only GENERATE is // used as key action is this // context return privateKey; diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPublicKeyContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPublicKeyContextTranslator.java index b0f14a52e..445e9efd5 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPublicKeyContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaPublicKeyContextTranslator.java @@ -19,16 +19,20 @@ */ package com.ibm.plugin.translation.translator.contexts; +import com.ibm.engine.model.Curve; import com.ibm.engine.model.IValue; import com.ibm.engine.model.KeyAction; import com.ibm.engine.model.context.DetectionContext; import com.ibm.engine.model.context.IDetectionContext; import com.ibm.engine.rule.IBundle; import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.mapper.pyca.PycaCurveMapper; import com.ibm.mapper.model.INode; import com.ibm.mapper.model.PublicKey; +import com.ibm.mapper.model.PublicKeyEncryption; import com.ibm.mapper.model.algorithms.DH; import com.ibm.mapper.model.algorithms.DSA; +import com.ibm.mapper.model.algorithms.ElGamal; import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.functionality.KeyGeneration; import com.ibm.mapper.utils.DetectionLocation; @@ -54,6 +58,7 @@ public final class PycaPublicKeyContextTranslator implements IContextTranslation case "DH" -> new DH(detectionLocation); case "RSA" -> new RSA(detectionLocation); case "DSA" -> new DSA(detectionLocation); + case "ELGAMAL" -> new ElGamal(detectionLocation); default -> null; }) .map( @@ -66,6 +71,18 @@ public final class PycaPublicKeyContextTranslator implements IContextTranslation // context return publicKey; }); + } else if (value instanceof Curve) { + final PycaCurveMapper mapper = new PycaCurveMapper(); + return mapper.parse(value.asString(), detectionLocation) + .map( + algo -> { + PublicKey publicKey = new PublicKey((PublicKeyEncryption) algo); + // currently only GENERATE is + // used as key action is this + // context + publicKey.put(new KeyGeneration(detectionLocation)); + return publicKey; + }); } return Optional.empty(); } diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaRandomContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaRandomContextTranslator.java new file mode 100644 index 000000000..4cd66fb3d --- /dev/null +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaRandomContextTranslator.java @@ -0,0 +1,57 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.translation.translator.contexts; + +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.IDetectionContext; +import com.ibm.engine.rule.IBundle; +import com.ibm.mapper.IContextTranslation; +import com.ibm.mapper.model.Algorithm; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.PseudorandomNumberGenerator; +import com.ibm.mapper.utils.DetectionLocation; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.sonar.plugins.python.api.tree.Tree; + +@SuppressWarnings("java:S1301") +public final class PycaRandomContextTranslator implements IContextTranslation { + + @Override + public @Nonnull Optional translate( + @Nonnull IBundle bundleIdentifier, + @Nonnull IValue value, + @Nonnull IDetectionContext detectionContext, + @Nonnull DetectionLocation detectionLocation) { + if (value instanceof ValueAction) { + return switch (value.asString().toUpperCase().trim()) { + case "PRNG" -> + Optional.of( + new Algorithm( + "PRNG", + PseudorandomNumberGenerator.class, + detectionLocation)); + default -> Optional.empty(); + }; + } + return Optional.empty(); + } +} diff --git a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java index 363c68378..e3ca43789 100644 --- a/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java +++ b/python/src/main/java/com/ibm/plugin/translation/translator/contexts/PycaSignatureContextTranslator.java @@ -30,7 +30,9 @@ import com.ibm.mapper.model.INode; import com.ibm.mapper.model.ProbabilisticSignatureScheme; import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.algorithms.DSS; import com.ibm.mapper.model.algorithms.ECDSA; +import com.ibm.mapper.model.algorithms.EdDSA; import com.ibm.mapper.model.algorithms.MGF1; import com.ibm.mapper.model.algorithms.RSA; import com.ibm.mapper.model.algorithms.RSAssaPSS; @@ -82,6 +84,10 @@ public final class PycaSignatureContextTranslator implements IContextTranslation }; } else { return switch (value.asString().toUpperCase().trim()) { + case "RSA" -> Optional.of(new RSA(Signature.class, detectionLocation)); + case "DSS" -> Optional.of(new DSS(detectionLocation)); + case "ECDSA" -> Optional.of(new ECDSA(detectionLocation)); + case "EDDSA" -> Optional.of(new EdDSA(detectionLocation)); case "MGF1" -> Optional.of(new MGF1(detectionLocation)); case "RSA-PSS" -> Optional.of(new RSAssaPSS(detectionLocation)); default -> Optional.empty(); diff --git a/python/src/test/files/rules/detection/aead/PycaAESGCMTestFile.py b/python/src/test/files/rules/detection/pyca/aead/PycaAESGCMTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/aead/PycaAESGCMTestFile.py rename to python/src/test/files/rules/detection/pyca/aead/PycaAESGCMTestFile.py diff --git a/python/src/test/files/rules/detection/aead/PycaChaCha20Poly1305TestFile.py b/python/src/test/files/rules/detection/pyca/aead/PycaChaCha20Poly1305TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/aead/PycaChaCha20Poly1305TestFile.py rename to python/src/test/files/rules/detection/pyca/aead/PycaChaCha20Poly1305TestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/DSA/PycaDSANumbersTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/DSA/PycaDSANumbersTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/DSA/PycaDSASignTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSASignTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/DSA/PycaDSASignTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSASignTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSANumbersTestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/RSA/PycaRSANumbersTestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSASign1TestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign1TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/RSA/PycaRSASign1TestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign1TestFile.py diff --git a/python/src/test/files/rules/detection/asymmetric/RSA/PycaRSASign2TestFile.py b/python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign2TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/asymmetric/RSA/PycaRSASign2TestFile.py rename to python/src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign2TestFile.py diff --git a/python/src/test/files/rules/detection/fernet/PycaFernetDecryptTestFile.py b/python/src/test/files/rules/detection/pyca/fernet/PycaFernetDecryptTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/fernet/PycaFernetDecryptTestFile.py rename to python/src/test/files/rules/detection/pyca/fernet/PycaFernetDecryptTestFile.py diff --git a/python/src/test/files/rules/detection/fernet/PycaFernetEncryptTestFile.py b/python/src/test/files/rules/detection/pyca/fernet/PycaFernetEncryptTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/fernet/PycaFernetEncryptTestFile.py rename to python/src/test/files/rules/detection/pyca/fernet/PycaFernetEncryptTestFile.py diff --git a/python/src/test/files/rules/detection/fernet/PycaMultiFernetTestFile.py b/python/src/test/files/rules/detection/pyca/fernet/PycaMultiFernetTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/fernet/PycaMultiFernetTestFile.py rename to python/src/test/files/rules/detection/pyca/fernet/PycaMultiFernetTestFile.py diff --git a/python/src/test/files/rules/detection/hash/PycaHashDirectTest.py b/python/src/test/files/rules/detection/pyca/hash/PycaHashDirectTest.py similarity index 100% rename from python/src/test/files/rules/detection/hash/PycaHashDirectTest.py rename to python/src/test/files/rules/detection/pyca/hash/PycaHashDirectTest.py diff --git a/python/src/test/files/rules/detection/kdf/PycaConcatKDFHMACTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHMACTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaConcatKDFHMACTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHMACTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaConcatKDFHashTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHashTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaConcatKDFHashTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHashTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaHKDFExpandTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaHKDFExpandTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaHKDFExpandTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaHKDFExpandTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaHKDFTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaHKDFTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaHKDFTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaHKDFTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaKBKDFCMACTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaKBKDFCMACTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaKBKDFCMACTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaKBKDFCMACTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaKBKDFHMACTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaKBKDFHMACTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaKBKDFHMACTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaKBKDFHMACTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaPBKDF2TestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaPBKDF2TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaPBKDF2TestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaPBKDF2TestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaScryptTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaScryptTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaScryptTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaScryptTestFile.py diff --git a/python/src/test/files/rules/detection/kdf/PycaX963KDFTestFile.py b/python/src/test/files/rules/detection/pyca/kdf/PycaX963KDFTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/kdf/PycaX963KDFTestFile.py rename to python/src/test/files/rules/detection/pyca/kdf/PycaX963KDFTestFile.py diff --git a/python/src/test/files/rules/detection/keyagreement/PycaKeyAgreementTestFile.py b/python/src/test/files/rules/detection/pyca/keyagreement/PycaKeyAgreementTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/keyagreement/PycaKeyAgreementTestFile.py rename to python/src/test/files/rules/detection/pyca/keyagreement/PycaKeyAgreementTestFile.py diff --git a/python/src/test/files/rules/detection/mac/PycaCMACTestFile.py b/python/src/test/files/rules/detection/pyca/mac/PycaCMACTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/mac/PycaCMACTestFile.py rename to python/src/test/files/rules/detection/pyca/mac/PycaCMACTestFile.py diff --git a/python/src/test/files/rules/detection/mac/PycaHMACTestFile.py b/python/src/test/files/rules/detection/pyca/mac/PycaHMACTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/mac/PycaHMACTestFile.py rename to python/src/test/files/rules/detection/pyca/mac/PycaHMACTestFile.py diff --git a/python/src/test/files/rules/detection/mac/PycaMacDetectionInCustomFunctionTestFile.py b/python/src/test/files/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/mac/PycaMacDetectionInCustomFunctionTestFile.py rename to python/src/test/files/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTestFile.py diff --git a/python/src/test/files/rules/detection/mac/PycaPoly1305TestFile.py b/python/src/test/files/rules/detection/pyca/mac/PycaPoly1305TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/mac/PycaPoly1305TestFile.py rename to python/src/test/files/rules/detection/pyca/mac/PycaPoly1305TestFile.py diff --git a/python/src/test/files/rules/detection/padding/PycaPaddingTestFile.py b/python/src/test/files/rules/detection/pyca/padding/PycaPaddingTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/padding/PycaPaddingTestFile.py rename to python/src/test/files/rules/detection/pyca/padding/PycaPaddingTestFile.py diff --git a/python/src/test/files/rules/detection/symmetric/PycaCipher1TestFile.py b/python/src/test/files/rules/detection/pyca/symmetric/PycaCipher1TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/symmetric/PycaCipher1TestFile.py rename to python/src/test/files/rules/detection/pyca/symmetric/PycaCipher1TestFile.py diff --git a/python/src/test/files/rules/detection/symmetric/PycaCipher2TestFile.py b/python/src/test/files/rules/detection/pyca/symmetric/PycaCipher2TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/symmetric/PycaCipher2TestFile.py rename to python/src/test/files/rules/detection/pyca/symmetric/PycaCipher2TestFile.py diff --git a/python/src/test/files/rules/detection/pyca/symmetric/PycaCipher3TestFile.py b/python/src/test/files/rules/detection/pyca/symmetric/PycaCipher3TestFile.py new file mode 100644 index 000000000..45ca10c8c --- /dev/null +++ b/python/src/test/files/rules/detection/pyca/symmetric/PycaCipher3TestFile.py @@ -0,0 +1,36 @@ + +import os +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + +key64 = b"01234567" +key128 = b"0123456789abcdef" +key192 = b"0123456789abcdef01234567" +key256 = b"0123456789abcdef0123456789abcdef" + +iv = b"1234567890abcdef" +nonce = b"123456789012" +data = b"hello world!!!!!" + +# AES-CBC (invalid 64-bit key — should fail at runtime, but useful for static detection testing) +algo_small = algorithms.AES(key64) +c_small = Cipher(algo_small, modes.CBC(iv)) # Noncompliant {{(BlockCipher) AES-CBC}} +encryptor_small = c_small.encryptor() +ct_small = encryptor_small.update(data) + encryptor_small.finalize() + +# AES-CBC (128-bit) +algo_128 = algorithms.AES(key128) +c_128 = Cipher(algo_128, modes.CBC(iv)) # Noncompliant {{(BlockCipher) AES-CBC}} +encryptor_128 = c_128.encryptor() +ct_128 = encryptor_128.update(data) + encryptor_128.finalize() + +# AES-CBC (192-bit) +algo_192 = algorithms.AES(key192) +c_192 = Cipher(algo_192, modes.CBC(iv)) # Noncompliant {{(BlockCipher) AES-CBC}} +encryptor_192 = c_192.encryptor() +ct_192 = encryptor_192.update(data) + encryptor_192.finalize() + +# AES-CBC (256-bit) +algo_256 = algorithms.AES(key256) +c_256 = Cipher(algo_256, modes.CBC(iv)) # Noncompliant {{(BlockCipher) AES-CBC}} +encryptor_256 = c_256.encryptor() +ct_256 = encryptor_256.update(data) + encryptor_256.finalize() \ No newline at end of file diff --git a/python/src/test/files/rules/detection/symmetric/PycaStreamCipher1TestFile.py b/python/src/test/files/rules/detection/pyca/symmetric/PycaStreamCipher1TestFile.py similarity index 100% rename from python/src/test/files/rules/detection/symmetric/PycaStreamCipher1TestFile.py rename to python/src/test/files/rules/detection/pyca/symmetric/PycaStreamCipher1TestFile.py diff --git a/python/src/test/files/rules/detection/wrapping/PycaWrappingTestFile.py b/python/src/test/files/rules/detection/pyca/wrapping/PycaWrappingTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/wrapping/PycaWrappingTestFile.py rename to python/src/test/files/rules/detection/pyca/wrapping/PycaWrappingTestFile.py diff --git a/python/src/test/files/rules/detection/wrapping/PycaWrappingWithPaddingTestFile.py b/python/src/test/files/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTestFile.py similarity index 100% rename from python/src/test/files/rules/detection/wrapping/PycaWrappingWithPaddingTestFile.py rename to python/src/test/files/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTestFile.py diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/AESTestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/AESTestFile.py new file mode 100644 index 000000000..5135bac9e --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/AESTestFile.py @@ -0,0 +1,5 @@ +from Crypto.Cipher import AES + +key_aes = b"0123456789abcdef" +cipher_aes = AES.new(key_aes, AES.MODE_CBC) # Noncompliant {{(BlockCipher) AES-CBC}} +cipher_aes.encrypt(b'some message') diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/BlowfishTestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/BlowfishTestFile.py new file mode 100644 index 000000000..acbb3603a --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/BlowfishTestFile.py @@ -0,0 +1,4 @@ +from Crypto.Cipher import Blowfish + +key_blowfish = b"0123456789abcdef" +cipher_blowfish = Blowfish.new(key_blowfish, Blowfish.MODE_CBC) # Noncompliant {{(BlockCipher) Blowfish-CBC}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/CAST5TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/CAST5TestFile.py new file mode 100644 index 000000000..dd654fcea --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/CAST5TestFile.py @@ -0,0 +1,4 @@ +from Crypto.Cipher import CAST + +key_cast = b"0123456789abcdef" +cipher_cast = CAST.new(key_cast, CAST.MODE_CBC) # Noncompliant {{(BlockCipher) CAST5-CBC}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20Poly1305TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20Poly1305TestFile.py new file mode 100644 index 000000000..2f69ea0be --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20Poly1305TestFile.py @@ -0,0 +1,7 @@ +from Crypto.Cipher import ChaCha20_Poly1305 + +key_chacha20_poly1305 = b"0123456789abcdef0123456789abcdef" +nonce_chacha20_poly1305 = b"01234567" +cipher_chacha20_poly1305 = ChaCha20_Poly1305.new( # Noncompliant {{(AuthenticatedEncryption) ChaCha20-Poly1305}} + key=key_chacha20_poly1305, + nonce=nonce_chacha20_poly1305) diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20TestFile.py new file mode 100644 index 000000000..be90c8ffb --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/ChaCha20TestFile.py @@ -0,0 +1,5 @@ +from Crypto.Cipher import ChaCha20 + +key_chacha20 = b"0123456789abcdef0123456789abcdef" +nonce_chacha20 = b"01234567" +cipher_chacha20 = ChaCha20.new(key=key_chacha20, nonce=nonce_chacha20) # Noncompliant {{(StreamCipher) ChaCha20}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/DESTestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/DESTestFile.py new file mode 100644 index 000000000..bb956ab8e --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/DESTestFile.py @@ -0,0 +1,5 @@ +from Crypto.Cipher import DES + +key_des = b"01234567" +cipher_des = DES.new(key_des, DES.MODE_ECB) # Noncompliant {{(BlockCipher) DES-56-ECB}} +cipher_des.decrypt(b'some blob') diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/HPKETestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/HPKETestFile.py new file mode 100644 index 000000000..82489e8b1 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/HPKETestFile.py @@ -0,0 +1,10 @@ +from Crypto.PublicKey import ECC +from Crypto.Protocol import HPKE +from Crypto.Protocol.HPKE.AEAD import AES128_GCM + + +key = ECC.import_key(open("pub_key.pem").read()) # Noncompliant {{(Key) EC}} + +encryptor = HPKE.new(key, AES128_GCM) # Noncompliant {{(PublicKeyEncryption) EC}} + +ct_1 = encryptor.seal(b'Message 1') \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1OAEPTestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1OAEPTestFile.py new file mode 100644 index 000000000..79229a17b --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1OAEPTestFile.py @@ -0,0 +1,6 @@ +from Crypto.Cipher import PKCS1_OAEP +from Crypto.PublicKey import RSA +from Crypto.Hash import SHA256 + +key = RSA.importKey(open('public.pem').read()) +cipher = PKCS1_OAEP.new(key, SHA256) # Noncompliant {{(PublicKeyEncryption) RSA-OAEP}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1v15TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1v15TestFile.py new file mode 100644 index 000000000..adee56079 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/PKCS1v15TestFile.py @@ -0,0 +1,5 @@ +from Crypto.Cipher import PKCS1_v1_5 +from Crypto.PublicKey import RSA + +key = RSA.importKey(open('public.pem').read()) +cipher = PKCS1_v1_5.new(key) # Noncompliant {{(PublicKeyEncryption) RSA}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/RC2TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/RC2TestFile.py new file mode 100644 index 000000000..9ba68e2c4 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/RC2TestFile.py @@ -0,0 +1,4 @@ +from Crypto.Cipher import ARC2 + +key_arc2 = b"0123456789abcdef" +cipher_arc2 = ARC2.new(key_arc2, ARC2.MODE_CBC) # Noncompliant {{(BlockCipher) RC2-CBC}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/RC4TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/RC4TestFile.py new file mode 100644 index 000000000..c1d08fd5f --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/RC4TestFile.py @@ -0,0 +1,4 @@ +from Crypto.Cipher import ARC4 + +key_arc4 = b"0123456789abcdef" +cipher_arc4 = ARC4.new(key_arc4) # Noncompliant {{(StreamCipher) RC4}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/Salsa20TestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/Salsa20TestFile.py new file mode 100644 index 000000000..13d498ade --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/Salsa20TestFile.py @@ -0,0 +1,5 @@ +from Crypto.Cipher import Salsa20 + +key_salsa20 = b"0123456789abcdef0123456789abcdef" +nonce_salsa20 = b"01234567" +cipher_salsa20 = Salsa20.new(key=key_salsa20, nonce=nonce_salsa20) # Noncompliant {{(StreamCipher) Salsa20}} diff --git a/python/src/test/files/rules/detection/pycrypto/cipher/TripleDESTestFile.py b/python/src/test/files/rules/detection/pycrypto/cipher/TripleDESTestFile.py new file mode 100644 index 000000000..45ac67190 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/cipher/TripleDESTestFile.py @@ -0,0 +1,4 @@ +from Crypto.Cipher import DES3 + +key_3des = b"0123456789abcdef01234567" +cipher_3des = DES3.new(key_3des, DES3.MODE_CBC) # Noncompliant {{(BlockCipher) 3DES-CBC}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2bTestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2bTestFile.py new file mode 100644 index 000000000..190bcdf7f --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2bTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import BLAKE2b + +hash_blake2b = BLAKE2b.new() # Noncompliant {{(MessageDigest) BLAKE2b}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2sTestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2sTestFile.py new file mode 100644 index 000000000..5b5928fea --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/BLAKE2sTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import BLAKE2s + +hash_blake2s = BLAKE2s.new() # Noncompliant {{(MessageDigest) BLAKE2s}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/MD2TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/MD2TestFile.py new file mode 100644 index 000000000..8c1894f04 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/MD2TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import MD2 + +hash_md2 = MD2.new() # Noncompliant {{(MessageDigest) MD2}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/MD5TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/MD5TestFile.py new file mode 100644 index 000000000..4d830526b --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/MD5TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import MD5 + +hash_md5 = MD5.new() # Noncompliant {{(MessageDigest) MD5}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/RIPEMD160TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/RIPEMD160TestFile.py new file mode 100644 index 000000000..8c5d05634 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/RIPEMD160TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import RIPEMD160 + +hash_ripemd160 = RIPEMD160.new() # Noncompliant {{(MessageDigest) RIPEMD-160}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA1TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA1TestFile.py new file mode 100644 index 000000000..49966efe3 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA1TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA1 + +hash_sha1 = SHA1.new() # Noncompliant {{(MessageDigest) SHA-1}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA224TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA224TestFile.py new file mode 100644 index 000000000..b6cdab156 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA224TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA224 + +hash_sha224 = SHA224.new() # Noncompliant {{(MessageDigest) SHA-224}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA256TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA256TestFile.py new file mode 100644 index 000000000..46a45ccd2 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA256TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA256 + +hash_sha256 = SHA256.new() # Noncompliant {{(MessageDigest) SHA-256}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA384TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA384TestFile.py new file mode 100644 index 000000000..69c9d06d9 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA384TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA384 + +hash_sha384 = SHA384.new() # Noncompliant {{(MessageDigest) SHA-384}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA3_224TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_224TestFile.py new file mode 100644 index 000000000..c539ca916 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_224TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA3_224 + +hash_sha3_224 = SHA3_224.new() # Noncompliant {{(MessageDigest) SHA3-224}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA3_256TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_256TestFile.py new file mode 100644 index 000000000..c6975d0a1 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_256TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA3_256 + +hash_sha3_256 = SHA3_256.new() # Noncompliant {{(MessageDigest) SHA3-256}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA3_384TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_384TestFile.py new file mode 100644 index 000000000..03b29d382 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_384TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA3_384 + +hash_sha3_384 = SHA3_384.new() # Noncompliant {{(MessageDigest) SHA3-384}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA3_512TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_512TestFile.py new file mode 100644 index 000000000..338c5b305 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA3_512TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA3_512 + +hash_sha3_512 = SHA3_512.new() # Noncompliant {{(MessageDigest) SHA3-512}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/SHA512TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/SHA512TestFile.py new file mode 100644 index 000000000..d49f1fe8a --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/SHA512TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import SHA512 + +hash_sha512 = SHA512.new() # Noncompliant {{(MessageDigest) SHA-512}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/TupleHash128TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/TupleHash128TestFile.py new file mode 100644 index 000000000..cfdb54d28 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/TupleHash128TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import TupleHash128 + +hash_t128 = TupleHash128.new() # Noncompliant {{(ExtendableOutputFunction) TupleHash}} diff --git a/python/src/test/files/rules/detection/pycrypto/hash/cSHAKE256TestFile.py b/python/src/test/files/rules/detection/pycrypto/hash/cSHAKE256TestFile.py new file mode 100644 index 000000000..dc8db14df --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/hash/cSHAKE256TestFile.py @@ -0,0 +1,3 @@ +from Crypto.Hash import cSHAKE256 + +hash_t128 = cSHAKE256.new() # Noncompliant {{(ExtendableOutputFunction) cSHAKE256}} diff --git a/python/src/test/files/rules/detection/pycrypto/kdf/BcryptTestFile.py b/python/src/test/files/rules/detection/pycrypto/kdf/BcryptTestFile.py new file mode 100644 index 000000000..f99740baf --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/kdf/BcryptTestFile.py @@ -0,0 +1,6 @@ +from Crypto.Protocol.KDF import bcrypt + +def test_bcrypt(): + password = b"password" + salt = b"salt1234567890ab" + key = bcrypt(password, cost=10, salt=salt) # detected but not mapped diff --git a/python/src/test/files/rules/detection/pycrypto/kdf/HKDFTestFile.py b/python/src/test/files/rules/detection/pycrypto/kdf/HKDFTestFile.py new file mode 100644 index 000000000..9641cf2aa --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/kdf/HKDFTestFile.py @@ -0,0 +1,7 @@ +from Crypto.Protocol.KDF import HKDF +from Crypto.Hash import SHA512 + +def test_hkdf(): + secret = b"secret" + salt = b"salt1234567890ab" + key = HKDF(secret, 32, salt, SHA512) # Noncompliant {{(KeyDerivationFunction) HKDF-SHA-512}} diff --git a/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF1TestFile.py b/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF1TestFile.py new file mode 100644 index 000000000..92df75869 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF1TestFile.py @@ -0,0 +1,7 @@ +from Crypto.Protocol.KDF import PBKDF1 +from Crypto.Hash import SHA256 + +def test_pbkdf1(): + password = b"password" + salt = b"salt1234" + key = PBKDF1(password, salt, 16, 1000, SHA256) # Noncompliant {{(PasswordBasedKeyDerivationFunction) PBKDF1-SHA-256}} diff --git a/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF2TestFile.py b/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF2TestFile.py new file mode 100644 index 000000000..ec22b108c --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/kdf/PBKDF2TestFile.py @@ -0,0 +1,7 @@ +from Crypto.Protocol.KDF import PBKDF2 +from Crypto.Hash import SHA512 + +def test_pbkdf2(): + password = b"password" + salt = b"salt1234" + key = PBKDF2(password, salt, dkLen=64, count=1, hmac_hash_module=SHA512) # Noncompliant {{(PasswordBasedKeyDerivationFunction) PBKDF2-SHA-512}} diff --git a/python/src/test/files/rules/detection/pycrypto/kdf/ScryptTestFile.py b/python/src/test/files/rules/detection/pycrypto/kdf/ScryptTestFile.py new file mode 100644 index 000000000..3dacc3111 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/kdf/ScryptTestFile.py @@ -0,0 +1,6 @@ +from Crypto.Protocol.KDF import scrypt + +def test_scrypt(): + password = b"password" + salt = b"salt1234" + key = scrypt(password, salt, key_len=32, N=2**14, r=8, p=1, num_keys=1) # Noncompliant {{(PasswordBasedKeyDerivationFunction) scrypt}} diff --git a/python/src/test/files/rules/detection/pycrypto/keyagreement/DHTestFile.py b/python/src/test/files/rules/detection/pycrypto/keyagreement/DHTestFile.py new file mode 100644 index 000000000..07ec871fd --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/keyagreement/DHTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Protocol.DH import key_agreement + +shared_key = key_agreement(static_priv=None, static_pub=None) # Noncompliant {{(KeyAgreement) ECDH}} diff --git a/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTestFile.py b/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTestFile.py new file mode 100644 index 000000000..503745b60 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Protocol.DH import import_x25519_private_key + +priv = import_x25519_private_key(b'\x00' * 32) # Noncompliant {{(KeyAgreement) x25519}} diff --git a/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PublicKeyTestFile.py b/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PublicKeyTestFile.py new file mode 100644 index 000000000..d9ed9e66f --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/keyagreement/X25519PublicKeyTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Protocol.DH import import_x25519_public_key + +pub = import_x25519_public_key(b'\x00' * 32) # Noncompliant {{(KeyAgreement) x25519}} diff --git a/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PrivateKeyTestFile.py b/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PrivateKeyTestFile.py new file mode 100644 index 000000000..b5a936bad --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PrivateKeyTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Protocol.DH import import_x448_private_key + +priv = import_x448_private_key(b'\x00' * 56) # Noncompliant {{(KeyAgreement) x448}} diff --git a/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PublicKeyTestFile.py b/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PublicKeyTestFile.py new file mode 100644 index 000000000..617b6b617 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/keyagreement/X448PublicKeyTestFile.py @@ -0,0 +1,3 @@ +from Crypto.Protocol.DH import import_x448_public_key + +pub = import_x448_public_key(b'\x00' * 56) # Noncompliant {{(KeyAgreement) x448}} diff --git a/python/src/test/files/rules/detection/pycrypto/mac/CMACTestFile.py b/python/src/test/files/rules/detection/pycrypto/mac/CMACTestFile.py new file mode 100644 index 000000000..b2524fbfd --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/mac/CMACTestFile.py @@ -0,0 +1,5 @@ +from Crypto.Hash import CMAC +from Crypto.Cipher import AES + +key = b'some key' +cmac = CMAC.new(key, AES) # Noncompliant {{(Mac) CMAC-AES}} diff --git a/python/src/test/files/rules/detection/pycrypto/mac/HMACTestFile.py b/python/src/test/files/rules/detection/pycrypto/mac/HMACTestFile.py new file mode 100644 index 000000000..bc776cb2e --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/mac/HMACTestFile.py @@ -0,0 +1,4 @@ +from Crypto.Hash import HMAC, SHA256 + +secret = b'some secret' +hmac = HMAC.new(secret, digestmod=SHA256) # Noncompliant {{(Mac) HMAC-SHA-256}} diff --git a/python/src/test/files/rules/detection/pycrypto/publickey/DSATestFile.py b/python/src/test/files/rules/detection/pycrypto/publickey/DSATestFile.py new file mode 100644 index 000000000..1d78c629c --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/publickey/DSATestFile.py @@ -0,0 +1,6 @@ +from Crypto.PublicKey import DSA + +def test_dsa(): + key1 = DSA.generate(bits=2048) # Noncompliant {{(PrivateKey) DSA}} + key2 = DSA.construct((2,3), True) # Noncompliant {{(Key) DSA}} + key3 = DSA.import_key("abcdef") # Noncompliant {{(Key) DSA}} diff --git a/python/src/test/files/rules/detection/pycrypto/publickey/ECCTestFile.py b/python/src/test/files/rules/detection/pycrypto/publickey/ECCTestFile.py new file mode 100644 index 000000000..689c28638 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/publickey/ECCTestFile.py @@ -0,0 +1,6 @@ +from Crypto.PublicKey import ECC + +def test_ecc(): + key1 = ECC.generate(curve="Ed25519") # Noncompliant {{(PrivateKey) EC-Curve25519}} + key2 = ECC.construct(curve="Ed25519") # Noncompliant {{(Key) EC-Curve25519}} + key3 = ECC.import_key("abcdef") # Noncompliant {{(Key) EC}} diff --git a/python/src/test/files/rules/detection/pycrypto/publickey/ElGamalTestFile.py b/python/src/test/files/rules/detection/pycrypto/publickey/ElGamalTestFile.py new file mode 100644 index 000000000..1c9f52c14 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/publickey/ElGamalTestFile.py @@ -0,0 +1,5 @@ +from Crypto.PublicKey import ElGamal + +def test_elgamal(): + key1 = ElGamal.generate() # Noncompliant {{(PrivateKey) ElGamal}} + key2 = ElGamal.construct((2,3)) # Noncompliant {{(Key) ElGamal}} diff --git a/python/src/test/files/rules/detection/pycrypto/publickey/RSATestFile.py b/python/src/test/files/rules/detection/pycrypto/publickey/RSATestFile.py new file mode 100644 index 000000000..9699b98ad --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/publickey/RSATestFile.py @@ -0,0 +1,6 @@ +from Crypto.PublicKey import RSA + +def test_rsa(): + key1 = RSA.generate(bits=2048) # Noncompliant {{(PrivateKey) RSA}} + key2 = RSA.construct((2,3), True) # Noncompliant {{(Key) RSA}} + key3 = RSA.import_key("abcdef") # Noncompliant {{(Key) RSA}} diff --git a/python/src/test/files/rules/detection/pycrypto/signature/DSSSignTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/DSSSignTestFile.py new file mode 100644 index 000000000..7295f477e --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/DSSSignTestFile.py @@ -0,0 +1,9 @@ +from Crypto.Hash import SHA256 +from Crypto.PublicKey import DSA +from Crypto.Signature import DSS + +message = b'some message' +key = DSA.import_key(open('privkey.der').read()) # Noncompliant {{(Key) DSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +signer = DSS.new(key, 'fips-186-3') # Noncompliant {{(Signature) DSA-SHA-256}} +signature = signer.sign(h) \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/DSSVerifyTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/DSSVerifyTestFile.py new file mode 100644 index 000000000..a5e50a715 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/DSSVerifyTestFile.py @@ -0,0 +1,15 @@ +from Crypto.Hash import SHA256 +from Crypto.PublicKey import DSA +from Crypto.Signature import DSS + +message = b'some message' +key = DSA.import_key(open('pubkey.der').read()) # Noncompliant {{(Key) DSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +verifier = DSS.new(key, 'fips-186-3') # Noncompliant {{(Signature) DSA-SHA-256}} +signature = b'some signature' + +try: + verifier.verify(h, signature) + print("The message is authentic.") +except ValueError: + print("The message is not authentic.") \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/ECDSASignTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/ECDSASignTestFile.py new file mode 100644 index 000000000..f8e0479f3 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/ECDSASignTestFile.py @@ -0,0 +1,9 @@ +from Crypto.Hash import SHA256 +from Crypto.PublicKey import ECC +from Crypto.Signature import DSS + +message = b'some message' +key = ECC.import_key(open('privkey.der').read()) # Noncompliant {{(Key) EC}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +signer = DSS.new(key, 'fips-186-3') # Noncompliant {{(Signature) ECDSA-SHA-256}} +signature = signer.sign(h) \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/ECDSAVerifyTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/ECDSAVerifyTestFile.py new file mode 100644 index 000000000..e6a1806a7 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/ECDSAVerifyTestFile.py @@ -0,0 +1,15 @@ +from Crypto.Hash import SHA256 +from Crypto.PublicKey import ECC +from Crypto.Signature import DSS + +message = b'some message' +key = ECC.import_key(open('pubkey.der').read()) # Noncompliant {{(Key) EC}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +verifier = DSS.new(key, 'fips-186-3') # Noncompliant {{(Signature) ECDSA-SHA-256}} +signature = b'some signature' + +try: + verifier.verify(h, signature) + print("The message is authentic.") +except ValueError: + print("The message is not authentic.") \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/EdDSASignTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/EdDSASignTestFile.py new file mode 100644 index 000000000..debbc8912 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/EdDSASignTestFile.py @@ -0,0 +1,9 @@ +from Crypto.PublicKey import ECC +from Crypto.Signature import eddsa +from Crypto.Hash import SHA512 + +message = b'some message' +prehashed_message = SHA512.new(message) # Noncompliant {{(MessageDigest) SHA-512}} +key = ECC.import_key(open("private_ed25519.pem").read()) # Noncompliant {{(Key) EC}} +signer = eddsa.new(key, 'rfc8032') # Noncompliant {{(Signature) EdDSA}} +signature = signer.sign(prehashed_message) \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/EdDSAVerifyTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/EdDSAVerifyTestFile.py new file mode 100644 index 000000000..36002942b --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/EdDSAVerifyTestFile.py @@ -0,0 +1,15 @@ +from Crypto.PublicKey import ECC +from Crypto.Signature import eddsa +from Crypto.Hash import SHA512 + +message = b'some message' +key = ECC.import_key(open("public_ed25519.pem").read()) # Noncompliant {{(Key) EC}} +h = SHA512.new(message) # Noncompliant {{(MessageDigest) SHA-512}} +verifier = eddsa.new(key, 'rfc8032') # Noncompliant {{(Signature) EdDSA}} +signature = b'some signature' + +try: + verifier.verify(h, signature) + print("The message is authentic") +except ValueError: + print("The message is not authentic") \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15SignTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15SignTestFile.py new file mode 100644 index 000000000..512492b8f --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15SignTestFile.py @@ -0,0 +1,9 @@ +from Crypto.Signature import pkcs1_15 +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA + +message = b'To be signed' +key = RSA.import_key(open('private_key.der').read()) # Noncompliant {{(Key) RSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +scheme = pkcs1_15.new(key) # Noncompliant {{(Signature) RSA-PKCS1-1.5-SHA-256}} +signature = scheme.sign(h) \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15VerifyTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15VerifyTestFile.py new file mode 100644 index 000000000..c28633e0e --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/PKCS1v15VerifyTestFile.py @@ -0,0 +1,15 @@ +from Crypto.Signature import pkcs1_15 +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA + +message = b'To be signed' +key = RSA.import_key(open('private_key.der').read()) # Noncompliant {{(Key) RSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +scheme = pkcs1_15.new(key) # Noncompliant {{(Signature) RSA-PKCS1-1.5-SHA-256}} +signature = b'some sginature' + +try: + scheme.verify(h, signature) + print("The signature is valid.") +except (ValueError, TypeError): + print("The signature is not valid.") \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/PSSSignTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/PSSSignTestFile.py new file mode 100644 index 000000000..be000c574 --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/PSSSignTestFile.py @@ -0,0 +1,9 @@ +from Crypto.Signature import pss +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA + +message = b'To be signed' +key = RSA.import_key(open('private_key.der').read()) # Noncompliant {{(Key) RSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +scheme = pss.new(key) # Noncompliant {{(ProbabilisticSignatureScheme) RSA-PSS}} +signature = scheme.sign(h) \ No newline at end of file diff --git a/python/src/test/files/rules/detection/pycrypto/signature/PSSVerifyTestFile.py b/python/src/test/files/rules/detection/pycrypto/signature/PSSVerifyTestFile.py new file mode 100644 index 000000000..87b44fb1c --- /dev/null +++ b/python/src/test/files/rules/detection/pycrypto/signature/PSSVerifyTestFile.py @@ -0,0 +1,16 @@ +from Crypto.Signature import pss +from Crypto.Signature.pss import PSS_SigScheme +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA + +message = b'To be signed' +key = RSA.import_key(open('pubkey.der', 'rb').read()) # Noncompliant {{(Key) RSA}} +h = SHA256.new(message) # Noncompliant {{(MessageDigest) SHA-256}} +verifier = pss.new(key) # Noncompliant {{(ProbabilisticSignatureScheme) RSA-PSS}} +signature = b'some sginature' + +try: + verifier.verify(h, signature) + print("The signature is authentic.") +except (ValueError): + print("The signature is not authentic.") \ No newline at end of file diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaAESGCMTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAESGCMTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaAESGCMTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAESGCMTest.java index d3409b362..7811c3317 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaAESGCMTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaAESGCMTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.aead; +package com.ibm.plugin.rules.detection.pyca.aead; import static org.assertj.core.api.Assertions.assertThat; @@ -52,7 +52,7 @@ class PycaAESGCMTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/aead/PycaAESGCMTestFile.py", this); + "src/test/files/rules/detection/pyca/aead/PycaAESGCMTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaChaCha20Poly1305Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaChaCha20Poly1305Test.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaChaCha20Poly1305Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaChaCha20Poly1305Test.java index 004201c31..88c1b01f4 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/aead/PycaChaCha20Poly1305Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/aead/PycaChaCha20Poly1305Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.aead; +package com.ibm.plugin.rules.detection.pyca.aead; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaChaCha20Poly1305Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/aead/PycaChaCha20Poly1305TestFile.py", this); + "src/test/files/rules/detection/pyca/aead/PycaChaCha20Poly1305TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSANumbersTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTest.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSANumbersTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTest.java index 2178efc29..beebbd7c6 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSANumbersTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.DSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.DSA; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +47,8 @@ class PycaDSANumbersTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/DSA/PycaDSANumbersTestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSANumbersTestFile.py", + this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSASignTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSASignTest.java index 295196b08..1c4cfcafe 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DSA/PycaDSASignTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DSA/PycaDSASignTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.DSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.DSA; import static org.assertj.core.api.Assertions.assertThat; @@ -54,7 +54,7 @@ class PycaDSASignTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/DSA/PycaDSASignTestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/DSA/PycaDSASignTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java index 06ce44018..4097dcf75 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.DiffieHellman; +package com.ibm.plugin.rules.detection.pyca.asymmetric.DiffieHellman; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +47,7 @@ public final class PycaDiffieHellmanGenerateTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanGenerateTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java index bdd8bf7dc..26099a4a9 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.DiffieHellman; +package com.ibm.plugin.rules.detection.pyca.asymmetric.DiffieHellman; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,7 @@ class PycaDiffieHellmanNumbersTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/DiffieHellman/PycaDiffieHellmanNumbersTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java index dde89a44a..d34d4fa91 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +46,7 @@ class PycaEllipticCurveDeriveTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveDeriveTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java index ca421610e..c073991dc 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import static org.assertj.core.api.Assertions.assertThat; @@ -57,7 +57,7 @@ class PycaEllipticCurveKeyExchangeTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveKeyExchangeTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java similarity index 90% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java index 2c95fc794..9c1f7d79c 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import com.ibm.engine.detection.DetectionStore; import com.ibm.mapper.model.INode; @@ -38,7 +38,7 @@ class PycaEllipticCurveNumbersTest extends TestBase { @Test void test() { PythonCheckVerifier.verifyNoIssue( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveNumbersTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java index c6156730e..84e4928eb 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaEllipticCurveSign2Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSign2TestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java index 42e6c8347..e70a1c3df 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import static org.assertj.core.api.Assertions.assertThat; @@ -54,7 +54,7 @@ class PycaEllipticCurveSignTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveSignTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java similarity index 91% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java index ab38d7bcb..2941263c2 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.EllipticCurve; +package com.ibm.plugin.rules.detection.pyca.asymmetric.EllipticCurve; import com.ibm.engine.detection.DetectionStore; import com.ibm.mapper.model.INode; @@ -41,7 +41,7 @@ class PycaEllipticCurveVerifyTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py", + "src/test/files/rules/detection/pyca/asymmetric/EllipticCurve/PycaEllipticCurveVerifyTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTest.java index 416e98ba3..274f3bcd8 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSADecryptTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.RSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.RSA; import static org.assertj.core.api.Assertions.assertThat; @@ -58,7 +58,8 @@ class PycaRSADecryptTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/RSA/PycaRSADecryptTestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSADecryptTestFile.py", + this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSANumbersTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSANumbersTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTest.java index c78a44f64..5321621ee 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSANumbersTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.RSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.RSA; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +47,8 @@ class PycaRSANumbersTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/RSA/PycaRSANumbersTestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSANumbersTestFile.py", + this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign1Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign1Test.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign1Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign1Test.java index e57bdb78a..25c86fe9c 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign1Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign1Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.RSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.RSA; import static org.assertj.core.api.Assertions.assertThat; @@ -56,7 +56,7 @@ class PycaRSASign1Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/RSA/PycaRSASign1TestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign1TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign2Test.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign2Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign2Test.java index bb5181e56..c39328fa6 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/asymmetric/RSA/PycaRSASign2Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/asymmetric/RSA/PycaRSASign2Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.asymmetric.RSA; +package com.ibm.plugin.rules.detection.pyca.asymmetric.RSA; import static org.assertj.core.api.Assertions.assertThat; @@ -55,7 +55,7 @@ class PycaRSASign2Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/asymmetric/RSA/PycaRSASign2TestFile.py", this); + "src/test/files/rules/detection/pyca/asymmetric/RSA/PycaRSASign2TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetDecryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetDecryptTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetDecryptTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetDecryptTest.java index 10119414d..19f7d28cd 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetDecryptTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetDecryptTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.fernet; +package com.ibm.plugin.rules.detection.pyca.fernet; import static org.assertj.core.api.Assertions.assertThat; @@ -58,7 +58,7 @@ class PycaFernetDecryptTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/fernet/PycaFernetDecryptTestFile.py", this); + "src/test/files/rules/detection/pyca/fernet/PycaFernetDecryptTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetEncryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetEncryptTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetEncryptTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetEncryptTest.java index 759916b45..5ad5aa112 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaFernetEncryptTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaFernetEncryptTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.fernet; +package com.ibm.plugin.rules.detection.pyca.fernet; import static org.assertj.core.api.Assertions.assertThat; @@ -58,7 +58,7 @@ class PycaFernetEncryptTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/fernet/PycaFernetEncryptTestFile.py", this); + "src/test/files/rules/detection/pyca/fernet/PycaFernetEncryptTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaMultiFernetTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaMultiFernetTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaMultiFernetTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaMultiFernetTest.java index 36fe6893b..ac90ea5a5 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/fernet/PycaMultiFernetTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/fernet/PycaMultiFernetTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.fernet; +package com.ibm.plugin.rules.detection.pyca.fernet; import static org.assertj.core.api.Assertions.assertThat; @@ -59,7 +59,7 @@ class PycaMultiFernetTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/fernet/PycaMultiFernetTestFile.py", this); + "src/test/files/rules/detection/pyca/fernet/PycaMultiFernetTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/hash/PycaHashDirectTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHashDirectTest.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/hash/PycaHashDirectTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHashDirectTest.java index 73cef79d4..0e57b8a00 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/hash/PycaHashDirectTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/hash/PycaHashDirectTest.java @@ -1,6 +1,6 @@ /* * Sonar Cryptography Plugin - * Copyright (C) 2024 PQCA + * Copyright (C) 2026 PQCA * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.hash; +package com.ibm.plugin.rules.detection.pyca.hash; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +46,7 @@ class PycaHashDirectTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/hash/PycaHashDirectTest.py", this); + "src/test/files/rules/detection/pyca/hash/PycaHashDirectTest.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHMACTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHMACTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHMACTest.java index 4c72b5be8..2e7bd5711 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHMACTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHMACTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaConcatKDFHMACTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaConcatKDFHMACTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHMACTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHashTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHashTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHashTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHashTest.java index 68a47dbc9..e10a0c5f2 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaConcatKDFHashTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaConcatKDFHashTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -49,7 +49,7 @@ class PycaConcatKDFHashTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaConcatKDFHashTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaConcatKDFHashTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFExpandTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFExpandTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFExpandTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFExpandTest.java index 0eade96a6..585f7448b 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFExpandTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFExpandTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaHKDFExpandTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaHKDFExpandTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaHKDFExpandTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFTest.java index e7a4a5f16..1db1ba235 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaHKDFTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaHKDFTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -49,7 +49,8 @@ class PycaHKDFTest extends TestBase { @Test void test() { - PythonCheckVerifier.verify("src/test/files/rules/detection/kdf/PycaHKDFTestFile.py", this); + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pyca/kdf/PycaHKDFTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFCMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFCMACTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFCMACTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFCMACTest.java index 0436832c1..16e7df570 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFCMACTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFCMACTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaKBKDFCMACTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaKBKDFCMACTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaKBKDFCMACTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFHMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFHMACTest.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFHMACTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFHMACTest.java index ef0fad6b9..828cbf21d 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaKBKDFHMACTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaKBKDFHMACTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -52,7 +52,7 @@ class PycaKBKDFHMACTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaKBKDFHMACTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaKBKDFHMACTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaPBKDF2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaPBKDF2Test.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaPBKDF2Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaPBKDF2Test.java index bdcc9af1f..a714802e5 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaPBKDF2Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaPBKDF2Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -51,7 +51,7 @@ class PycaPBKDF2Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaPBKDF2TestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaPBKDF2TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaScryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaScryptTest.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaScryptTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaScryptTest.java index b137aabb5..f1a85a3fb 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaScryptTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaScryptTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,7 @@ class PycaScryptTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaScryptTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaScryptTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaX963KDFTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaX963KDFTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaX963KDFTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaX963KDFTest.java index 786fa46cb..9310d6380 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/kdf/PycaX963KDFTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/kdf/PycaX963KDFTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.kdf; +package com.ibm.plugin.rules.detection.pyca.kdf; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaX963KDFTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/kdf/PycaX963KDFTestFile.py", this); + "src/test/files/rules/detection/pyca/kdf/PycaX963KDFTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreementTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreementTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreementTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreementTest.java index bb88f0e77..9327a162f 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/keyagreement/PycaKeyAgreementTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/keyagreement/PycaKeyAgreementTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.keyagreement; +package com.ibm.plugin.rules.detection.pyca.keyagreement; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,8 @@ class PycaKeyAgreementTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/keyagreement/PycaKeyAgreementTestFile.py", this); + "src/test/files/rules/detection/pyca/keyagreement/PycaKeyAgreementTestFile.py", + this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaCMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaCMACTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaCMACTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaCMACTest.java index bbc0f3f2b..afeab14a3 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaCMACTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaCMACTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.mac; +package com.ibm.plugin.rules.detection.pyca.mac; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,8 @@ class PycaCMACTest extends TestBase { @Test void test() { - PythonCheckVerifier.verify("src/test/files/rules/detection/mac/PycaCMACTestFile.py", this); + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pyca/mac/PycaCMACTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaHMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaHMACTest.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaHMACTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaHMACTest.java index 9957f5381..374ee293d 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaHMACTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaHMACTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.mac; +package com.ibm.plugin.rules.detection.pyca.mac; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +47,8 @@ class PycaHMACTest extends TestBase { @Test void test() { - PythonCheckVerifier.verify("src/test/files/rules/detection/mac/PycaHMACTestFile.py", this); + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pyca/mac/PycaHMACTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaMacDetectionInCustomFunctionTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaMacDetectionInCustomFunctionTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTest.java index 9a89f28eb..e7806b573 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaMacDetectionInCustomFunctionTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.mac; +package com.ibm.plugin.rules.detection.pyca.mac; import static org.assertj.core.api.Assertions.assertThat; @@ -53,7 +53,7 @@ class PycaMacDetectionInCustomFunctionTest extends TestBase { @Test void testCryptographicOperationInCustomFunction() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/mac/PycaMacDetectionInCustomFunctionTestFile.py", + "src/test/files/rules/detection/pyca/mac/PycaMacDetectionInCustomFunctionTestFile.py", this); } diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaPoly1305Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaPoly1305Test.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaPoly1305Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaPoly1305Test.java index fecc5bd37..54872cf69 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/mac/PycaPoly1305Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/mac/PycaPoly1305Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.mac; +package com.ibm.plugin.rules.detection.pyca.mac; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,7 @@ class PycaPoly1305Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/mac/PycaPoly1305TestFile.py", this); + "src/test/files/rules/detection/pyca/mac/PycaPoly1305TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/padding/PycaPaddingTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPaddingTest.java similarity index 97% rename from python/src/test/java/com/ibm/plugin/rules/detection/padding/PycaPaddingTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPaddingTest.java index a2f29030a..7d3a43556 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/padding/PycaPaddingTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/padding/PycaPaddingTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.padding; +package com.ibm.plugin.rules.detection.pyca.padding; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +46,7 @@ class PycaPaddingTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/padding/PycaPaddingTestFile.py", this); + "src/test/files/rules/detection/pyca/padding/PycaPaddingTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher1Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher1Test.java similarity index 98% rename from python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher1Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher1Test.java index 73a1d6ebb..36834055c 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher1Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher1Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.symmetric; +package com.ibm.plugin.rules.detection.pyca.symmetric; import static org.assertj.core.api.Assertions.assertThat; @@ -50,7 +50,7 @@ class PycaCipher1Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/symmetric/PycaCipher1TestFile.py", this); + "src/test/files/rules/detection/pyca/symmetric/PycaCipher1TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher2Test.java similarity index 96% rename from python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher2Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher2Test.java index 74ac657a9..a69bca299 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaCipher2Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher2Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.symmetric; +package com.ibm.plugin.rules.detection.pyca.symmetric; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +45,7 @@ class PycaCipher2Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/symmetric/PycaCipher2TestFile.py", this); + "src/test/files/rules/detection/pyca/symmetric/PycaCipher2TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher3Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher3Test.java new file mode 100644 index 000000000..0ad33a939 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaCipher3Test.java @@ -0,0 +1,115 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2024 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pyca.symmetric; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Encrypt; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +class PycaCipher3Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pyca/symmetric/PycaCipher3TestFile.py", this); + } + + @SuppressWarnings("null") + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value0 = detectionStore.getDetectionValues().get(0); + assertThat(value0).isInstanceOf(Algorithm.class); + assertThat(value0.asString()).isEqualTo("AES"); + + List> store_1 = + getStoresOfValueType(CipherAction.class, detectionStore.getChildren()); + assertThat(store_1).isNotNull(); + for (DetectionStore store : store_1) { + assertThat(store.getDetectionValues()).hasSize(1); + assertThat(store.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value0_1 = store.getDetectionValues().get(0); + assertThat(value0_1).isInstanceOf(CipherAction.class); + assertThat(value0_1.asString()).isEqualTo("ENCRYPT"); + } + + // /* + // * Translation + // */ + assertThat(nodes).hasSize(1); + + // BlockCipher + INode blockCipherNode = nodes.get(0); + assertThat(blockCipherNode.getKind()).isEqualTo(BlockCipher.class); + assertThat(blockCipherNode.getChildren()).hasSize(4); + assertThat(blockCipherNode.asString()).isEqualTo("AES-CBC"); + + // Mode under BlockCipher + INode modeNode = blockCipherNode.getChildren().get(Mode.class); + assertThat(modeNode).isNotNull(); + assertThat(modeNode.getChildren()).isEmpty(); + assertThat(modeNode.asString()).isEqualTo("CBC"); + + // Oid under BlockCipher + INode oidNode = blockCipherNode.getChildren().get(Oid.class); + assertThat(oidNode).isNotNull(); + assertThat(oidNode.getChildren()).isEmpty(); + assertThat(oidNode.asString()).isEqualTo("2.16.840.1.101.3.4.1"); + + // Encrypt under BlockCipher + INode encryptNode = blockCipherNode.getChildren().get(Encrypt.class); + assertThat(encryptNode).isNotNull(); + assertThat(encryptNode.getChildren()).isEmpty(); + assertThat(encryptNode.asString()).isEqualTo("ENCRYPT"); + + // BlockSize under BlockCipher + INode blockSizeNode1 = blockCipherNode.getChildren().get(BlockSize.class); + assertThat(blockSizeNode1).isNotNull(); + assertThat(blockSizeNode1.getChildren()).isEmpty(); + assertThat(blockSizeNode1.asString()).isEqualTo("128"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaStreamCipher1Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaStreamCipher1Test.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaStreamCipher1Test.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaStreamCipher1Test.java index 7c5b1f339..98776e4f0 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/symmetric/PycaStreamCipher1Test.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/symmetric/PycaStreamCipher1Test.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.symmetric; +package com.ibm.plugin.rules.detection.pyca.symmetric; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +44,7 @@ class PycaStreamCipher1Test extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/symmetric/PycaStreamCipher1TestFile.py", this); + "src/test/files/rules/detection/pyca/symmetric/PycaStreamCipher1TestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingTest.java index 003eaaf9c..9c1a34897 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.wrapping; +package com.ibm.plugin.rules.detection.pyca.wrapping; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +44,7 @@ class PycaWrappingTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/wrapping/PycaWrappingTestFile.py", this); + "src/test/files/rules/detection/pyca/wrapping/PycaWrappingTestFile.py", this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingWithPaddingTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTest.java similarity index 95% rename from python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingWithPaddingTest.java rename to python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTest.java index 37d0bb788..bfeeec87f 100644 --- a/python/src/test/java/com/ibm/plugin/rules/detection/wrapping/PycaWrappingWithPaddingTest.java +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTest.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.ibm.plugin.rules.detection.wrapping; +package com.ibm.plugin.rules.detection.pyca.wrapping; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +44,8 @@ class PycaWrappingWithPaddingTest extends TestBase { @Test void test() { PythonCheckVerifier.verify( - "src/test/files/rules/detection/wrapping/PycaWrappingWithPaddingTestFile.py", this); + "src/test/files/rules/detection/pyca/wrapping/PycaWrappingWithPaddingTestFile.py", + this); } @Override diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/AESTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/AESTest.java new file mode 100644 index 000000000..d84e3b32f --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/AESTest.java @@ -0,0 +1,100 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.mapper.model.Oid; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class AESTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/AESTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("AES"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_CBC"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(4); + assertThat(cipher.asString()).isEqualTo("AES-CBC"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("CBC"); + + INode oid = cipher.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.1"); + + INode blockSize = cipher.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("128"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/BlowfishTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/BlowfishTest.java new file mode 100644 index 000000000..22cbae93c --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/BlowfishTest.java @@ -0,0 +1,88 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class BlowfishTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/BlowfishTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("Blowfish"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_CBC"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(1); + assertThat(cipher.asString()).isEqualTo("Blowfish-CBC"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("CBC"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/CAST5Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/CAST5Test.java new file mode 100644 index 000000000..5c174d392 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/CAST5Test.java @@ -0,0 +1,94 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class CAST5Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/CAST5TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("CAST5"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_CBC"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(2); + assertThat(cipher.asString()).isEqualTo("CAST5-CBC"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("CBC"); + + INode blockSize = cipher.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("64"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Poly1305Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Poly1305Test.java new file mode 100644 index 000000000..8a8c6a9c7 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Poly1305Test.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.AuthenticatedEncryption; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ChaCha20Poly1305Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/ChaCha20Poly1305TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("ChaCha20Poly1305"); + assertThat(detectionStore.getChildren()).isEmpty(); + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(AuthenticatedEncryption.class); + assertThat(cipher.getChildren()).hasSize(1); + assertThat(cipher.asString()).isEqualTo("ChaCha20-Poly1305"); + + INode messageDigest = cipher.getChildren().get(MessageDigest.class); + assertThat(messageDigest).isNotNull(); + assertThat(messageDigest.getChildren()).hasSize(1); + assertThat(messageDigest.asString()).isEqualTo("Poly1305"); + + INode digest = messageDigest.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Test.java new file mode 100644 index 000000000..443a3b348 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/ChaCha20Test.java @@ -0,0 +1,68 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.StreamCipher; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ChaCha20Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/ChaCha20TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("ChaCha20"); + assertThat(detectionStore.getChildren()).isEmpty(); + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(StreamCipher.class); + assertThat(cipher.getChildren()).isEmpty(); + assertThat(cipher.asString()).isEqualTo("ChaCha20"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/DESTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/DESTest.java new file mode 100644 index 000000000..cee58d89c --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/DESTest.java @@ -0,0 +1,100 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.Mode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DESTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/DESTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("DES"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_ECB"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(4); + assertThat(cipher.asString()).isEqualTo("DES-56-ECB"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("ECB"); + + INode keyLength = cipher.getChildren().get(KeyLength.class); + assertThat(keyLength).isNotNull(); + assertThat(keyLength.getChildren()).isEmpty(); + assertThat(keyLength.asString()).isEqualTo("56"); + + INode blockSize = cipher.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("64"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/HPKETest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/HPKETest.java new file mode 100644 index 000000000..f35187237 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/HPKETest.java @@ -0,0 +1,205 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.mapper.model.AuthenticatedEncryption; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.Mode; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.Encrypt; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class HPKETest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/HPKETestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + switch (findingId) { + case 0 -> assertECCImportKey(detectionStore, nodes); + case 1 -> assertHPKENew(detectionStore, nodes); + default -> throw new AssertionError("Unexpected findingId: " + findingId); + } + } + + // ------------------------------------------------------------------------- + // findingId == 0 (ECC.import_key(...)) + // ------------------------------------------------------------------------- + + private void assertECCImportKey( + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(KeyContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(KeyAction.class); + assertThat(((KeyAction) value).getAction()).isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + /* + * Translation: Key(EC) → KeyGeneration, PublicKeyEncryption(EC) → Oid + */ + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.asString()).isEqualTo("EC"); + assertThat(root.getChildren()).hasSize(2); + + INode pke = root.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.asString()).isEqualTo("EC"); + assertThat(pke.getChildren()).hasSize(1); + INode oid = pke.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.asString()).isEqualTo("1.2.840.10045.2.1"); + + INode keyGen = root.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + } + + // ------------------------------------------------------------------------- + // findingId == 1 (HPKE.new(key, AES128_GCM)) + // ------------------------------------------------------------------------- + + private void assertHPKENew( + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("HPKE"); + + DetectionStore encryptStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + assertThat(encryptStore).isNotNull(); + assertThat(encryptStore.getDetectionValues()).hasSize(1); + IValue encryptValue = encryptStore.getDetectionValues().get(0); + assertThat(encryptValue).isInstanceOf(CipherAction.class); + assertThat(((CipherAction) encryptValue).getAction()) + .isEqualTo(CipherAction.Action.ENCRYPT); + + DetectionStore keyStore = + getStoreOfValueType(KeyAction.class, detectionStore.getChildren()); + assertThat(keyStore).isNotNull(); + assertThat(keyStore.getDetectionValues()).hasSize(1); + assertThat(((KeyAction) keyStore.getDetectionValues().get(0)).getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + + /* + * Translation (enriched): + * PublicKeyEncryption(EC) + * ├─ Encrypt + * ├─ Oid(1.2.840.10045.2.1) + * └─ AuthenticatedEncryption(AES-128-GCM) + * ├─ BlockSize(128) + * ├─ Oid(2.16.840.1.101.3.4.1.6) + * ├─ KeyLength(128) + * └─ Mode(GCM) + * └─ (Key) EC + * └─ (PublicKeyEncryption) EC + * └─ (Oid) 1.2.840.10045.2.1 + * └─ (KeyGeneration) KEYGENERATION + * └─ (Oid) 1.2.840.10045.2.1 + */ + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PublicKeyEncryption.class); + assertThat(root.asString()).isEqualTo("EC"); + assertThat(root.getChildren()).hasSize(4); + + INode encrypt = root.getChildren().get(Encrypt.class); + assertThat(encrypt).isNotNull(); + assertThat(encrypt.asString()).isEqualTo("ENCRYPT"); + + INode rootOid = root.getChildren().get(Oid.class); + assertThat(rootOid).isNotNull(); + assertThat(rootOid.asString()).isEqualTo("1.2.840.10045.2.1"); + + INode aead = root.getChildren().get(AuthenticatedEncryption.class); + assertThat(aead).isNotNull(); + assertThat(aead.asString()).isEqualTo("AES-128-GCM"); + assertThat(aead.getChildren()).hasSize(4); + + INode blockSize = aead.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.asString()).isEqualTo("128"); + + INode aeadOid = aead.getChildren().get(Oid.class); + assertThat(aeadOid).isNotNull(); + assertThat(aeadOid.asString()).isEqualTo("2.16.840.1.101.3.4.1.6"); + + INode keyLength = aead.getChildren().get(KeyLength.class); + assertThat(keyLength).isNotNull(); + assertThat(keyLength.asString()).isEqualTo("128"); + + INode mode = aead.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.asString()).isEqualTo("GCM"); + + INode key = root.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("EC"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.10045.2.1"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1OAEPTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1OAEPTest.java new file mode 100644 index 000000000..f7d5dac8a --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1OAEPTest.java @@ -0,0 +1,98 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Padding; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PKCS1OAEPTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/PKCS1OAEPTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("PKCS1_OAEP"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + DetectionStore keyStore = + getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); + if (keyStore != null) { + assertThat(keyStore.getDetectionValues()).hasSize(1); + assertThat(keyStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + assertThat(keyStore.getDetectionValues().get(0)).isInstanceOf(Algorithm.class); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(PublicKeyEncryption.class); + assertThat(cipher.getChildren()).hasSize(2); + assertThat(cipher.asString()).isEqualTo("RSA-OAEP"); + + INode oid = cipher.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.7"); + + INode padding = cipher.getChildren().get(Padding.class); + assertThat(padding).isNotNull(); + assertThat(padding.getChildren()).isEmpty(); + assertThat(padding.asString()).isEqualTo("OAEP"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1v15Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1v15Test.java new file mode 100644 index 000000000..ae488c6ff --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/PKCS1v15Test.java @@ -0,0 +1,89 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Padding; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PKCS1v15Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/PKCS1v15TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("PKCS1_v1_5"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(PublicKeyEncryption.class); + assertThat(cipher.getChildren()).hasSize(2); + assertThat(cipher.asString()).isEqualTo("RSA"); + + INode oid = cipher.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.1"); + + INode padding = cipher.getChildren().get(Padding.class); + assertThat(padding).isNotNull(); + assertThat(padding.getChildren()).isEmpty(); + assertThat(padding.asString()).isEqualTo("PKCS1"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC2Test.java new file mode 100644 index 000000000..bd456aa8b --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC2Test.java @@ -0,0 +1,88 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class RC2Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/RC2TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RC2"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_CBC"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(1); + assertThat(cipher.asString()).isEqualTo("RC2-CBC"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("CBC"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC4Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC4Test.java new file mode 100644 index 000000000..c5e0b7336 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/RC4Test.java @@ -0,0 +1,77 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.StreamCipher; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class RC4Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/RC4TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RC4"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(StreamCipher.class); + assertThat(cipher.getChildren()).isEmpty(); + assertThat(cipher.asString()).isEqualTo("RC4"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/Salsa20Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/Salsa20Test.java new file mode 100644 index 000000000..5805dcca0 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/Salsa20Test.java @@ -0,0 +1,83 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.CipherAction; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.StreamCipher; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class Salsa20Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/Salsa20TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("Salsa20"); + + DetectionStore actionStore = + getStoreOfValueType(CipherAction.class, detectionStore.getChildren()); + if (actionStore != null) { + assertThat(actionStore.getDetectionValues().get(0).asString()) + .satisfiesAnyOf( + s -> assertThat(s).isEqualTo("ENCRYPT"), + s -> assertThat(s).isEqualTo("DECRYPT")); + } + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(StreamCipher.class); + assertThat(cipher.getChildren()).hasSize(1); + assertThat(cipher.asString()).isEqualTo("Salsa20"); + + INode keyLength = cipher.getChildren().get(KeyLength.class); + assertThat(keyLength).isNotNull(); + assertThat(keyLength.getChildren()).isEmpty(); + assertThat(keyLength.asString()).isEqualTo("128"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/TripleDESTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/TripleDESTest.java new file mode 100644 index 000000000..2437eb099 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/cipher/TripleDESTest.java @@ -0,0 +1,84 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.cipher; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.CipherContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class TripleDESTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/cipher/TripleDESTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(CipherContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("3DES"); + + DetectionStore modeStore = + getStoreOfValueType(com.ibm.engine.model.Mode.class, detectionStore.getChildren()); + assertThat(modeStore).isNotNull(); + assertThat(modeStore.getDetectionValues().get(0).asString()).isEqualTo("MODE_CBC"); + + assertThat(nodes).hasSize(1); + INode cipher = nodes.get(0); + assertThat(cipher.getKind()).isEqualTo(BlockCipher.class); + assertThat(cipher.getChildren()).hasSize(2); + assertThat(cipher.asString()).isEqualTo("3DES-CBC"); + + INode mode = cipher.getChildren().get(Mode.class); + assertThat(mode).isNotNull(); + assertThat(mode.getChildren()).isEmpty(); + assertThat(mode.asString()).isEqualTo("CBC"); + + INode blockSize = cipher.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("64"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2bTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2bTest.java new file mode 100644 index 000000000..f1c54fe17 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2bTest.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.SaltLength; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class BLAKE2bTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/BLAKE2bTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("BLAKE2b"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(2); + assertThat(md.asString()).isEqualTo("BLAKE2b"); + + INode saltLength = md.getChildren().get(SaltLength.class); + assertThat(saltLength).isNotNull(); + assertThat(saltLength.getChildren()).isEmpty(); + assertThat(saltLength.asString()).isEqualTo("128"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2sTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2sTest.java new file mode 100644 index 000000000..53a984914 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/BLAKE2sTest.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.SaltLength; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class BLAKE2sTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/BLAKE2sTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("BLAKE2s"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(2); + assertThat(md.asString()).isEqualTo("BLAKE2s"); + + INode saltLength = md.getChildren().get(SaltLength.class); + assertThat(saltLength).isNotNull(); + assertThat(saltLength.getChildren()).isEmpty(); + assertThat(saltLength.asString()).isEqualTo("64"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD2Test.java new file mode 100644 index 000000000..9603d7ff5 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD2Test.java @@ -0,0 +1,86 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class MD2Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/MD2TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("MD2"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(3); + assertThat(md.asString()).isEqualTo("MD2"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("128"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("128"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD5Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD5Test.java new file mode 100644 index 000000000..4841ea4b2 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/MD5Test.java @@ -0,0 +1,86 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class MD5Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/MD5TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("MD5"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(3); + assertThat(md.asString()).isEqualTo("MD5"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("128"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/RIPEMD160Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/RIPEMD160Test.java new file mode 100644 index 000000000..9ae8ab849 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/RIPEMD160Test.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class RIPEMD160Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/RIPEMD160TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RIPEMD160"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(2); + assertThat(md.asString()).isEqualTo("RIPEMD-160"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("160"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA1Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA1Test.java new file mode 100644 index 000000000..43f1f8a88 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA1Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA1Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA1TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA1"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-1"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.3.14.3.2.26"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("160"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA224Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA224Test.java new file mode 100644 index 000000000..55dc5bb4c --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA224Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA224Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA224TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA224"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-224"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.4"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("224"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA256Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA256Test.java new file mode 100644 index 000000000..7984cf644 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA256Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA256Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA256TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA256"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-256"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA384Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA384Test.java new file mode 100644 index 000000000..8a4698440 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA384Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA384Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA384TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA384"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-384"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1024"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.2"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("384"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_224Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_224Test.java new file mode 100644 index 000000000..028159f49 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_224Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA3_224Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA3_224TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA3_224"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA3-224"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1152"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.7"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("224"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_256Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_256Test.java new file mode 100644 index 000000000..59872895c --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_256Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA3_256Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA3_256TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA3_256"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA3-256"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1088"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.8"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_384Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_384Test.java new file mode 100644 index 000000000..15e7518cb --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_384Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA3_384Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA3_384TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA3_384"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA3-384"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("832"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.9"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("384"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_512Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_512Test.java new file mode 100644 index 000000000..1b757a736 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA3_512Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA3_512Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA3_512TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA3_512"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA3-512"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("576"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.10"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("512"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA512Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA512Test.java new file mode 100644 index 000000000..9d0b7d92d --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/SHA512Test.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class SHA512Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/SHA512TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("SHA512"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-512"); + + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1024"); + + INode oid = md.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.2.3"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("512"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/TupleHash128Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/TupleHash128Test.java new file mode 100644 index 000000000..4ba2c2ad0 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/TupleHash128Test.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class TupleHash128Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/TupleHash128TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("TupleHash128"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(2); + assertThat(md.asString()).isEqualTo("TupleHash"); + + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("128"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/cSHAKE256Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/cSHAKE256Test.java new file mode 100644 index 000000000..82a4b7db7 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/hash/cSHAKE256Test.java @@ -0,0 +1,80 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.hash; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.DigestContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.ParameterSetIdentifier; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class cSHAKE256Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/hash/cSHAKE256TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(DigestContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("cSHAKE256"); + + assertThat(nodes).hasSize(1); + INode md = nodes.get(0); + assertThat(md).isInstanceOf(MessageDigest.class); + assertThat(md.getChildren()).hasSize(2); + assertThat(md.asString()).isEqualTo("cSHAKE256"); + + INode parameterSetIdentifier = md.getChildren().get(ParameterSetIdentifier.class); + assertThat(parameterSetIdentifier).isNotNull(); + assertThat(parameterSetIdentifier.getChildren()).isEmpty(); + assertThat(parameterSetIdentifier.asString()).isEqualTo("256"); + + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/BcryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/BcryptTest.java new file mode 100644 index 000000000..0d05c8fc4 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/BcryptTest.java @@ -0,0 +1,76 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.AlgorithmParameter; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.mapper.model.INode; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class BcryptTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verifyNoIssue( + "src/test/files/rules/detection/pycrypto/kdf/BcryptTestFile.py", this); + } + + @Override + @SuppressWarnings("unchecked") + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(2); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("bcrypt"); + + IValue iterValue = + detectionStore.getDetectionValues().stream() + .filter(v -> v instanceof AlgorithmParameter) + .findFirst() + .orElse(null); + assertThat(iterValue).isNotNull(); + assertThat(((AlgorithmParameter) iterValue).getKind()) + .isEqualTo(AlgorithmParameter.Kind.ITERATIONS); + assertThat(iterValue.asString()).isEqualTo("10"); + + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(nodes).isEmpty(); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/HKDFTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/HKDFTest.java new file mode 100644 index 000000000..d58e52ca7 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/HKDFTest.java @@ -0,0 +1,102 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyDerivationFunction; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.algorithms.HKDF; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyDerivation; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class HKDFTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/kdf/HKDFTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("HKDF"); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("256"); + + DetectionStore algorithmStore = + getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); + assertThat(algorithmStore).isNotNull(); + assertThat(algorithmStore.getDetectionValues().get(0).asString()).isEqualTo("SHA512"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyDerivationFunction.class); + assertThat(root).isInstanceOf(HKDF.class); + assertThat(root.getChildren()).hasSize(3); + assertThat(root.asString()).isEqualTo("HKDF-SHA-512"); + + INode md = root.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-512"); + assertThat(md.getChildren().get(DigestSize.class).asString()).isEqualTo("512"); + assertThat(md.getChildren().get(Oid.class).asString()).isEqualTo("2.16.840.1.101.3.4.2.3"); + assertThat(md.getChildren().get(Digest.class).asString()).isEqualTo("DIGEST"); + assertThat(md.getChildren().get(BlockSize.class).asString()).isEqualTo("1024"); + + assertThat(root.getChildren().get(KeyLength.class).asString()).isEqualTo("256"); + assertThat(root.getChildren().get(KeyDerivation.class).asString()) + .isEqualTo("KEYDERIVATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF1Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF1Test.java new file mode 100644 index 000000000..50318602e --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF1Test.java @@ -0,0 +1,117 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PasswordBasedKeyDerivationFunction; +import com.ibm.mapper.model.algorithms.PBKDF1; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyDerivation; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PBKDF1Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/kdf/PBKDF1TestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("PBKDF1"); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues()).hasSize(1); + assertThat(keySizeStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + assertThat(keySizeStore.getDetectionValues().get(0)).isInstanceOf(KeySize.class); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("128"); + + DetectionStore algorithmStore = + getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); + assertThat(algorithmStore).isNotNull(); + assertThat(algorithmStore.getDetectionValues()).hasSize(1); + assertThat(algorithmStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + assertThat(algorithmStore.getDetectionValues().get(0)).isInstanceOf(Algorithm.class); + assertThat(algorithmStore.getDetectionValues().get(0).asString()).isEqualTo("SHA256"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PasswordBasedKeyDerivationFunction.class); + assertThat(root).isInstanceOf(PBKDF1.class); + assertThat(root.getChildren()).hasSize(3); + assertThat(root.asString()).isEqualTo("PBKDF1-SHA-256"); + + INode md = root.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-256"); + + assertThat(md.getChildren().get(DigestSize.class)).isNotNull(); + assertThat(md.getChildren().get(DigestSize.class).asString()).isEqualTo("256"); + assertThat(md.getChildren().get(Oid.class)).isNotNull(); + assertThat(md.getChildren().get(Oid.class).asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + assertThat(md.getChildren().get(Digest.class)).isNotNull(); + assertThat(md.getChildren().get(Digest.class).asString()).isEqualTo("DIGEST"); + assertThat(md.getChildren().get(BlockSize.class)).isNotNull(); + assertThat(md.getChildren().get(BlockSize.class).asString()).isEqualTo("512"); + + assertThat(root.getChildren().get(KeyLength.class)).isNotNull(); + assertThat(root.getChildren().get(KeyLength.class).asString()).isEqualTo("128"); + assertThat(root.getChildren().get(KeyDerivation.class)).isNotNull(); + assertThat(root.getChildren().get(KeyDerivation.class).asString()) + .isEqualTo("KEYDERIVATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF2Test.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF2Test.java new file mode 100644 index 000000000..7cc7a3057 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/PBKDF2Test.java @@ -0,0 +1,114 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.AlgorithmParameter; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PasswordBasedKeyDerivationFunction; +import com.ibm.mapper.model.algorithms.PBKDF2; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyDerivation; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PBKDF2Test extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/kdf/PBKDF2TestFile.py", this); + } + + @Override + @SuppressWarnings("unchecked") + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(2); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("PBKDF2"); + + IValue iterValue = + detectionStore.getDetectionValues().stream() + .filter(v -> v instanceof AlgorithmParameter) + .findFirst() + .orElse(null); + assertThat(iterValue).isNotNull(); + assertThat(((AlgorithmParameter) iterValue).getKind()) + .isEqualTo(AlgorithmParameter.Kind.ITERATIONS); + assertThat(iterValue.asString()).isEqualTo("1"); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("512"); + + DetectionStore algorithmStore = + getStoreOfValueType(Algorithm.class, detectionStore.getChildren()); + assertThat(algorithmStore).isNotNull(); + assertThat(algorithmStore.getDetectionValues().get(0).asString()).isEqualTo("SHA512"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PasswordBasedKeyDerivationFunction.class); + assertThat(root).isInstanceOf(PBKDF2.class); + assertThat(root.getChildren()).hasSize(3); + assertThat(root.asString()).isEqualTo("PBKDF2-SHA-512"); + + INode md = root.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.getChildren()).hasSize(4); + assertThat(md.asString()).isEqualTo("SHA-512"); + assertThat(md.getChildren().get(DigestSize.class).asString()).isEqualTo("512"); + assertThat(md.getChildren().get(Oid.class).asString()).isEqualTo("2.16.840.1.101.3.4.2.3"); + assertThat(md.getChildren().get(Digest.class).asString()).isEqualTo("DIGEST"); + assertThat(md.getChildren().get(BlockSize.class).asString()).isEqualTo("1024"); + + assertThat(root.getChildren().get(KeyLength.class).asString()).isEqualTo("512"); + assertThat(root.getChildren().get(KeyDerivation.class).asString()) + .isEqualTo("KEYDERIVATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/ScryptTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/ScryptTest.java new file mode 100644 index 000000000..9aaac66ae --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/kdf/ScryptTest.java @@ -0,0 +1,82 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.kdf; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyDerivationFunctionContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.PasswordBasedKeyDerivationFunction; +import com.ibm.mapper.model.algorithms.Scrypt; +import com.ibm.mapper.model.functionality.KeyDerivation; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ScryptTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/kdf/ScryptTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyDerivationFunctionContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("scrypt"); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("256"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PasswordBasedKeyDerivationFunction.class); + assertThat(root).isInstanceOf(Scrypt.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("scrypt"); + + assertThat(root.getChildren().get(KeyLength.class).asString()).isEqualTo("256"); + assertThat(root.getChildren().get(KeyDerivation.class).asString()) + .isEqualTo("KEYDERIVATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/DHTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/DHTest.java new file mode 100644 index 000000000..8d2f23ea5 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/DHTest.java @@ -0,0 +1,76 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.algorithms.ECDH; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DHTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/keyagreement/DHTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyAgreementContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(detectionStore.getDetectionValues().get(0)).isInstanceOf(ValueAction.class); + assertThat(detectionStore.getDetectionValues().get(0).asString()).isEqualTo("ECDH"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyAgreement.class); + assertThat(root).isInstanceOf(ECDH.class); + assertThat(root.asString()).isEqualTo("ECDH"); + + assertThat(root.getChildren().get(Oid.class)).isNotNull(); + assertThat(root.getChildren().get(Oid.class).asString()).isEqualTo("1.3.132.1.12"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(KeyGeneration.class).asString()) + .isEqualTo("KEYGENERATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTest.java new file mode 100644 index 000000000..3f57606e3 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTest.java @@ -0,0 +1,78 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class X25519PrivateKeyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/keyagreement/X25519PrivateKeyTestFile.py", + this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyAgreementContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(detectionStore.getDetectionValues().get(0)).isInstanceOf(KeyAction.class); + assertThat(detectionStore.getDetectionValues().get(0).asString()).isEqualTo("GENERATION"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyAgreement.class); + assertThat(root.asString()).isEqualTo("x25519"); + + assertThat(root.getChildren().get(EllipticCurve.class)).isNotNull(); + assertThat(root.getChildren().get(EllipticCurve.class).asString()).isEqualTo("Curve25519"); + assertThat(root.getChildren().get(Oid.class)).isNotNull(); + assertThat(root.getChildren().get(Oid.class).asString()).isEqualTo("1.3.101.110"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(KeyGeneration.class).asString()) + .isEqualTo("KEYGENERATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PublicKeyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PublicKeyTest.java new file mode 100644 index 000000000..929a0ff09 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X25519PublicKeyTest.java @@ -0,0 +1,78 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class X25519PublicKeyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/keyagreement/X25519PublicKeyTestFile.py", + this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyAgreementContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(detectionStore.getDetectionValues().get(0)).isInstanceOf(KeyAction.class); + assertThat(detectionStore.getDetectionValues().get(0).asString()).isEqualTo("GENERATION"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyAgreement.class); + assertThat(root.asString()).isEqualTo("x25519"); + + assertThat(root.getChildren().get(EllipticCurve.class)).isNotNull(); + assertThat(root.getChildren().get(EllipticCurve.class).asString()).isEqualTo("Curve25519"); + assertThat(root.getChildren().get(Oid.class)).isNotNull(); + assertThat(root.getChildren().get(Oid.class).asString()).isEqualTo("1.3.101.110"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(KeyGeneration.class).asString()) + .isEqualTo("KEYGENERATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PrivateKeyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PrivateKeyTest.java new file mode 100644 index 000000000..953007c19 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PrivateKeyTest.java @@ -0,0 +1,78 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class X448PrivateKeyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/keyagreement/X448PrivateKeyTestFile.py", + this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyAgreementContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(detectionStore.getDetectionValues().get(0)).isInstanceOf(KeyAction.class); + assertThat(detectionStore.getDetectionValues().get(0).asString()).isEqualTo("GENERATION"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyAgreement.class); + assertThat(root.asString()).isEqualTo("x448"); + + assertThat(root.getChildren().get(EllipticCurve.class)).isNotNull(); + assertThat(root.getChildren().get(EllipticCurve.class).asString()).isEqualTo("Curve448"); + assertThat(root.getChildren().get(Oid.class)).isNotNull(); + assertThat(root.getChildren().get(Oid.class).asString()).isEqualTo("1.3.101.111"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(KeyGeneration.class).asString()) + .isEqualTo("KEYGENERATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PublicKeyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PublicKeyTest.java new file mode 100644 index 000000000..016bcf1d3 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/keyagreement/X448PublicKeyTest.java @@ -0,0 +1,78 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.keyagreement; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyAgreementContext; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.KeyAgreement; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class X448PublicKeyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/keyagreement/X448PublicKeyTestFile.py", + this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyAgreementContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + assertThat(detectionStore.getDetectionValues().get(0)).isInstanceOf(KeyAction.class); + assertThat(detectionStore.getDetectionValues().get(0).asString()).isEqualTo("GENERATION"); + + assertThat(nodes).hasSize(1); + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(KeyAgreement.class); + assertThat(root.asString()).isEqualTo("x448"); + + assertThat(root.getChildren().get(EllipticCurve.class)).isNotNull(); + assertThat(root.getChildren().get(EllipticCurve.class).asString()).isEqualTo("Curve448"); + assertThat(root.getChildren().get(Oid.class)).isNotNull(); + assertThat(root.getChildren().get(Oid.class).asString()).isEqualTo("1.3.101.111"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(KeyGeneration.class).asString()) + .isEqualTo("KEYGENERATION"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/CMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/CMACTest.java new file mode 100644 index 000000000..5daf5dbff --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/CMACTest.java @@ -0,0 +1,92 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.mac; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.context.MacContext; +import com.ibm.mapper.model.BlockCipher; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mac; +import com.ibm.mapper.model.Oid; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class CMACTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/mac/CMACTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + /* + * Detection Store + */ + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(MacContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(Algorithm.class); + assertThat(value.asString()).isEqualTo("AES"); + + /* + * Translation + */ + assertThat(nodes).hasSize(1); + + INode mac = nodes.get(0); + assertThat(mac).isInstanceOf(Mac.class); + assertThat(mac.asString()).isEqualTo("CMAC-AES"); + assertThat(mac.getChildren()).hasSize(2); + + INode cipher = mac.getChildren().get(BlockCipher.class); + assertThat(cipher).isNotNull(); + assertThat(cipher.asString()).isEqualTo("AES"); + + INode blockSize = cipher.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("128"); + + INode oid = cipher.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.1"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/HMACTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/HMACTest.java new file mode 100644 index 000000000..b62ec4557 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/mac/HMACTest.java @@ -0,0 +1,91 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.mac; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Algorithm; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.context.MacContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Mac; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class HMACTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/mac/HMACTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + assertThat(findingId).isZero(); + + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()).isInstanceOf(MacContext.class); + assertThat(detectionStore.getChildren()).isEmpty(); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(Algorithm.class); + assertThat(value.asString()).isEqualTo("SHA256"); + + assertThat(nodes).hasSize(1); + INode mac = nodes.get(0); + assertThat(mac).isInstanceOf(Mac.class); + assertThat(mac.asString()).isEqualTo("HMAC-SHA-256"); + assertThat(mac.getChildren()).hasSize(3); + + INode digest = mac.getChildren().get(MessageDigest.class); + assertThat(digest).isNotNull(); + assertThat(digest.asString()).isEqualTo("SHA-256"); + assertThat(digest.getChildren()).hasSize(4); + + assertThat(digest.getChildren().get(Digest.class)).isNotNull(); + assertThat(digest.getChildren().get(Digest.class).asString()).isEqualTo("DIGEST"); + assertThat(digest.getChildren().get(BlockSize.class)).isNotNull(); + assertThat(digest.getChildren().get(BlockSize.class).asString()).isEqualTo("512"); + assertThat(digest.getChildren().get(Oid.class)).isNotNull(); + assertThat(digest.getChildren().get(Oid.class).asString()) + .isEqualTo("2.16.840.1.101.3.4.2.1"); + assertThat(digest.getChildren().get(DigestSize.class)).isNotNull(); + assertThat(digest.getChildren().get(DigestSize.class).asString()).isEqualTo("256"); + + assertThat(mac.getChildren().get(Oid.class)).isNotNull(); + assertThat(mac.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.113549.2.9"); + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/DSATest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/DSATest.java new file mode 100644 index 000000000..c87ae21af --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/DSATest.java @@ -0,0 +1,147 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.publickey; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DSATest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/publickey/DSATestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + switch (findingId) { + case 0 -> { + // DSA.generate(bits=2048) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(PrivateKeyContext.class); + IValue v = detectionStore.getDetectionValues().get(0); + assertThat(v).isInstanceOf(KeyAction.class); + assertThat(((KeyAction) v).getAction()) + .isEqualTo(KeyAction.Action.PRIVATE_KEY_GENERATION); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("2048"); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PrivateKey.class); + assertThat(root.getChildren()).hasSize(3); + assertThat(root.asString()).isEqualTo("DSA"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + + INode innerKey = root.getChildren().get(PrivateKey.class); + assertThat(innerKey).isNotNull(); + assertThat(innerKey.getChildren()).hasSize(3); + assertThat(innerKey.getChildren().get(KeyLength.class).asString()) + .isEqualTo("2048"); + INode innerSig = innerKey.getChildren().get(Signature.class); + assertThat(innerSig).isNotNull(); + assertThat(innerSig.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.10040.4.1"); + + INode outerSig = root.getChildren().get(Signature.class); + assertThat(outerSig).isNotNull(); + assertThat(outerSig.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.10040.4.1"); + } + case 1 -> { + // DSA.construct(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("DSA"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat( + root.getChildren() + .get(Signature.class) + .getChildren() + .get(Oid.class) + .asString()) + .isEqualTo("1.2.840.10040.4.1"); + } + case 2 -> { + // DSA.import_key(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("DSA"); + assertThat( + root.getChildren() + .get(Signature.class) + .getChildren() + .get(Oid.class) + .asString()) + .isEqualTo("1.2.840.10040.4.1"); + } + default -> throw new AssertionError("Unexpected findingId: " + findingId); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ECCTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ECCTest.java new file mode 100644 index 000000000..6ea001dcc --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ECCTest.java @@ -0,0 +1,141 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.publickey; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.Curve; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.mapper.model.EllipticCurve; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ECCTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/publickey/ECCTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + switch (findingId) { + case 0 -> { + // ECC.generate(curve="Ed25519") + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(PrivateKeyContext.class); + IValue v = detectionStore.getDetectionValues().get(0); + assertThat(v).isInstanceOf(Curve.class); + assertThat(v.asString()).isEqualTo("Ed25519"); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PrivateKey.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("EC-Curve25519"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + + INode pke = root.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren()).hasSize(2); + assertThat(pke.asString()).isEqualTo("EC-Curve25519"); + assertThat(pke.getChildren().get(EllipticCurve.class).asString()) + .isEqualTo("Curve25519"); + assertThat(pke.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.10045.2.1"); + } + case 1 -> { + // ECC.construct(curve="Ed25519") + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + + DetectionStore curveStore = + getStoreOfValueType(Curve.class, detectionStore.getChildren()); + assertThat(curveStore).isNotNull(); + assertThat(curveStore.getDetectionValues().get(0).asString()).isEqualTo("Ed25519"); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("EC-Curve25519"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + + INode pke = root.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(EllipticCurve.class).asString()) + .isEqualTo("Curve25519"); + assertThat(pke.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.10045.2.1"); + } + case 2 -> { + // ECC.import_key(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("EC"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat( + root.getChildren() + .get(PublicKeyEncryption.class) + .getChildren() + .get(Oid.class) + .asString()) + .isEqualTo("1.2.840.10045.2.1"); + } + default -> throw new AssertionError("Unexpected findingId: " + findingId); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ElGamalTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ElGamalTest.java new file mode 100644 index 000000000..51084023d --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/ElGamalTest.java @@ -0,0 +1,101 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.publickey; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ElGamalTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/publickey/ElGamalTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + switch (findingId) { + case 0 -> { + // ElGamal.generate() + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(PrivateKeyContext.class); + IValue v = detectionStore.getDetectionValues().get(0); + assertThat(v).isInstanceOf(KeyAction.class); + assertThat(((KeyAction) v).getAction()) + .isEqualTo(KeyAction.Action.PRIVATE_KEY_GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PrivateKey.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("ElGamal"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(PublicKeyEncryption.class)).isNotNull(); + assertThat(root.getChildren().get(PublicKeyEncryption.class).getChildren()) + .isEmpty(); + } + case 1 -> { + // ElGamal.construct(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("ElGamal"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(PublicKeyEncryption.class)).isNotNull(); + assertThat(root.getChildren().get(PublicKeyEncryption.class).getChildren()) + .isEmpty(); + } + default -> throw new AssertionError("Unexpected findingId: " + findingId); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/RSATest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/RSATest.java new file mode 100644 index 000000000..c0460f1e3 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/publickey/RSATest.java @@ -0,0 +1,153 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.publickey; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.KeyAction; +import com.ibm.engine.model.KeySize; +import com.ibm.engine.model.context.KeyContext; +import com.ibm.engine.model.context.PrivateKeyContext; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.KeyLength; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PrivateKey; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class RSATest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/publickey/RSATestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + switch (findingId) { + case 0 -> { + // RSA.generate(bits=2048) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(PrivateKeyContext.class); + IValue v = detectionStore.getDetectionValues().get(0); + assertThat(v).isInstanceOf(KeyAction.class); + assertThat(((KeyAction) v).getAction()) + .isEqualTo(KeyAction.Action.PRIVATE_KEY_GENERATION); + + DetectionStore keySizeStore = + getStoreOfValueType(KeySize.class, detectionStore.getChildren()); + assertThat(keySizeStore).isNotNull(); + assertThat(keySizeStore.getDetectionValues().get(0).asString()).isEqualTo("2048"); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(PrivateKey.class); + assertThat(root.getChildren()).hasSize(3); + assertThat(root.asString()).isEqualTo("RSA"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + + INode innerKey = root.getChildren().get(PrivateKey.class); + assertThat(innerKey).isNotNull(); + assertThat(innerKey.getChildren()).hasSize(3); + assertThat(innerKey.asString()).isEqualTo("RSA"); + assertThat(innerKey.getChildren().get(KeyLength.class).asString()) + .isEqualTo("2048"); + assertThat(innerKey.getChildren().get(KeyGeneration.class)).isNotNull(); + INode innerPke = innerKey.getChildren().get(PublicKeyEncryption.class); + assertThat(innerPke).isNotNull(); + assertThat(innerPke.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.113549.1.1.1"); + + INode outerPke = root.getChildren().get(PublicKeyEncryption.class); + assertThat(outerPke).isNotNull(); + assertThat(outerPke.getChildren().get(Oid.class).asString()) + .isEqualTo("1.2.840.113549.1.1.1"); + } + case 1 -> { + // RSA.construct(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat(detectionStore.getDetectionValues().get(0)) + .isInstanceOf(KeyAction.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("RSA"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat(root.getChildren().get(PublicKeyEncryption.class)).isNotNull(); + assertThat( + root.getChildren() + .get(PublicKeyEncryption.class) + .getChildren() + .get(Oid.class) + .asString()) + .isEqualTo("1.2.840.113549.1.1.1"); + } + case 2 -> { + // RSA.import_key(...) + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(KeyContext.class); + assertThat( + ((KeyAction) detectionStore.getDetectionValues().get(0)) + .getAction()) + .isEqualTo(KeyAction.Action.GENERATION); + assertThat(detectionStore.getChildren()).isEmpty(); + + INode root = nodes.get(0); + assertThat(root.getKind()).isEqualTo(Key.class); + assertThat(root.getChildren()).hasSize(2); + assertThat(root.asString()).isEqualTo("RSA"); + assertThat(root.getChildren().get(KeyGeneration.class)).isNotNull(); + assertThat( + root.getChildren() + .get(PublicKeyEncryption.class) + .getChildren() + .get(Oid.class) + .asString()) + .isEqualTo("1.2.840.113549.1.1.1"); + } + default -> throw new AssertionError("Unexpected findingId: " + findingId); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSSignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSSignTest.java new file mode 100644 index 000000000..1f63da7a4 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSSignTest.java @@ -0,0 +1,128 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DSSSignTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/DSSSignTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("DSS"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("SIGN"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("DSA-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.3.2"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("DSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode sign = sig.getChildren().get(Sign.class); + assertThat(sign).isNotNull(); + assertThat(sign.getChildren()).isEmpty(); + assertThat(sign.asString()).isEqualTo("SIGN"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSVerifyTest.java new file mode 100644 index 000000000..f953bb88d --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/DSSVerifyTest.java @@ -0,0 +1,128 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DSSVerifyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/DSSVerifyTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("DSS"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("VERIFY"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("DSA-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("2.16.840.1.101.3.4.3.2"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("DSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode verify = sig.getChildren().get(Verify.class); + assertThat(verify).isNotNull(); + assertThat(verify.getChildren()).isEmpty(); + assertThat(verify.asString()).isEqualTo("VERIFY"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSASignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSASignTest.java new file mode 100644 index 000000000..44c82d828 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSASignTest.java @@ -0,0 +1,132 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ECDSASignTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/ECDSASignTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("ECDSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("SIGN"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("ECDSA-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.10045.4.3.2"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("EC"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.10045.2.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode sign = sig.getChildren().get(Sign.class); + assertThat(sign).isNotNull(); + assertThat(sign.getChildren()).isEmpty(); + assertThat(sign.asString()).isEqualTo("SIGN"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSAVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSAVerifyTest.java new file mode 100644 index 000000000..e34b57645 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/ECDSAVerifyTest.java @@ -0,0 +1,132 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class ECDSAVerifyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/ECDSAVerifyTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("ECDSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("VERIFY"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("ECDSA-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.10045.4.3.2"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("EC"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.10045.2.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode verify = sig.getChildren().get(Verify.class); + assertThat(verify).isNotNull(); + assertThat(verify.getChildren()).isEmpty(); + assertThat(verify.asString()).isEqualTo("VERIFY"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSASignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSASignTest.java new file mode 100644 index 000000000..8f4f6d267 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSASignTest.java @@ -0,0 +1,127 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class EdDSASignTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/EdDSASignTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("EDDSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("SIGN"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(3); + assertThat(sig.asString()).isEqualTo("EdDSA"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("EC"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.10045.2.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-512"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.3"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("512"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1024"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode sign = sig.getChildren().get(Sign.class); + assertThat(sign).isNotNull(); + assertThat(sign.getChildren()).isEmpty(); + assertThat(sign.asString()).isEqualTo("SIGN"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSAVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSAVerifyTest.java new file mode 100644 index 000000000..12582c85d --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/EdDSAVerifyTest.java @@ -0,0 +1,127 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class EdDSAVerifyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/EdDSAVerifyTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("EDDSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("VERIFY"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(3); + assertThat(sig.asString()).isEqualTo("EdDSA"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("EC"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + assertThat(pke.getChildren().get(Oid.class).asString()).isEqualTo("1.2.840.10045.2.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-512"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.3"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("512"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("1024"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode verify = sig.getChildren().get(Verify.class); + assertThat(verify).isNotNull(); + assertThat(verify.getChildren()).isEmpty(); + assertThat(verify.asString()).isEqualTo("VERIFY"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15SignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15SignTest.java new file mode 100644 index 000000000..63d6d5485 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15SignTest.java @@ -0,0 +1,135 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PKCS1v15SignTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/PKCS1v15SignTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("SIGN"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("RSA-PKCS1-1.5-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.11"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("RSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + INode pkeOid = pke.getChildren().get(Oid.class); + assertThat(pkeOid).isNotNull(); + assertThat(pkeOid.getChildren()).isEmpty(); + assertThat(pkeOid.asString()).isEqualTo("1.2.840.113549.1.1.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode sign = sig.getChildren().get(Sign.class); + assertThat(sign).isNotNull(); + assertThat(sign.getChildren()).isEmpty(); + assertThat(sign.asString()).isEqualTo("SIGN"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15VerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15VerifyTest.java new file mode 100644 index 000000000..58b0cb8a4 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PKCS1v15VerifyTest.java @@ -0,0 +1,136 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.Signature; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PKCS1v15VerifyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/PKCS1v15VerifyTestFile.py", + this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RSA"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("VERIFY"); + + // translation + assertThat(nodes).hasSize(1); + INode sig = nodes.get(0); + assertThat(sig.getKind()).isEqualTo(Signature.class); + assertThat(sig.getChildren()).hasSize(4); + assertThat(sig.asString()).isEqualTo("RSA-PKCS1-1.5-SHA-256"); + + INode oid = sig.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.11"); + + INode key = sig.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("RSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + INode pkeOid = pke.getChildren().get(Oid.class); + assertThat(pkeOid).isNotNull(); + assertThat(pkeOid.getChildren()).isEmpty(); + assertThat(pkeOid.asString()).isEqualTo("1.2.840.113549.1.1.1"); + + INode md = sig.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode verify = sig.getChildren().get(Verify.class); + assertThat(verify).isNotNull(); + assertThat(verify.getChildren()).isEmpty(); + assertThat(verify.asString()).isEqualTo("VERIFY"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSSignTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSSignTest.java new file mode 100644 index 000000000..f87f57004 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSSignTest.java @@ -0,0 +1,135 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.ProbabilisticSignatureScheme; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Sign; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PSSSignTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/PSSSignTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RSA-PSS"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("SIGN"); + + // translation + assertThat(nodes).hasSize(1); + INode pss = nodes.get(0); + assertThat(pss.getKind()).isEqualTo(ProbabilisticSignatureScheme.class); + assertThat(pss.getChildren()).hasSize(4); + assertThat(pss.asString()).isEqualTo("RSA-PSS"); + + INode oid = pss.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.10"); + + INode key = pss.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("RSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + INode pkeOid = pke.getChildren().get(Oid.class); + assertThat(pkeOid).isNotNull(); + assertThat(pkeOid.getChildren()).isEmpty(); + assertThat(pkeOid.asString()).isEqualTo("1.2.840.113549.1.1.1"); + + INode md = pss.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode sign = pss.getChildren().get(Sign.class); + assertThat(sign).isNotNull(); + assertThat(sign.getChildren()).isEmpty(); + assertThat(sign.asString()).isEqualTo("SIGN"); + } + } +} diff --git a/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSVerifyTest.java b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSVerifyTest.java new file mode 100644 index 000000000..6ada8cfb9 --- /dev/null +++ b/python/src/test/java/com/ibm/plugin/rules/detection/pycrypto/signature/PSSVerifyTest.java @@ -0,0 +1,135 @@ +/* + * Sonar Cryptography Plugin + * Copyright (C) 2026 PQCA + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.plugin.rules.detection.pycrypto.signature; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.ibm.engine.detection.DetectionStore; +import com.ibm.engine.model.IValue; +import com.ibm.engine.model.SignatureAction; +import com.ibm.engine.model.ValueAction; +import com.ibm.engine.model.context.SignatureContext; +import com.ibm.mapper.model.BlockSize; +import com.ibm.mapper.model.DigestSize; +import com.ibm.mapper.model.INode; +import com.ibm.mapper.model.Key; +import com.ibm.mapper.model.MessageDigest; +import com.ibm.mapper.model.Oid; +import com.ibm.mapper.model.ProbabilisticSignatureScheme; +import com.ibm.mapper.model.PublicKeyEncryption; +import com.ibm.mapper.model.functionality.Digest; +import com.ibm.mapper.model.functionality.KeyGeneration; +import com.ibm.mapper.model.functionality.Verify; +import com.ibm.plugin.TestBase; +import java.util.List; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.Test; +import org.sonar.plugins.python.api.PythonCheck; +import org.sonar.plugins.python.api.PythonVisitorContext; +import org.sonar.plugins.python.api.symbols.Symbol; +import org.sonar.plugins.python.api.tree.Tree; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class PSSVerifyTest extends TestBase { + + @Test + void test() { + PythonCheckVerifier.verify( + "src/test/files/rules/detection/pycrypto/signature/PSSVerifyTestFile.py", this); + } + + @Override + public void asserts( + int findingId, + @Nonnull DetectionStore detectionStore, + @Nonnull List nodes) { + if (findingId == 2) { + // detection store + assertThat(detectionStore.getDetectionValues()).hasSize(1); + assertThat(detectionStore.getDetectionValueContext()) + .isInstanceOf(SignatureContext.class); + IValue value = detectionStore.getDetectionValues().get(0); + assertThat(value).isInstanceOf(ValueAction.class); + assertThat(value.asString()).isEqualTo("RSA-PSS"); + + DetectionStore sigStore = + getStoreOfValueType(SignatureAction.class, detectionStore.getChildren()); + assertThat(sigStore).isNotNull(); + assertThat(sigStore.getDetectionValues()).hasSize(1); + assertThat(sigStore.getDetectionValueContext()).isInstanceOf(SignatureContext.class); + IValue sigValue = sigStore.getDetectionValues().get(0); + assertThat(sigValue).isInstanceOf(SignatureAction.class); + assertThat(sigValue.asString()).isEqualTo("VERIFY"); + + // translation + assertThat(nodes).hasSize(1); + INode pss = nodes.get(0); + assertThat(pss.getKind()).isEqualTo(ProbabilisticSignatureScheme.class); + assertThat(pss.getChildren()).hasSize(4); + assertThat(pss.asString()).isEqualTo("RSA-PSS"); + + INode oid = pss.getChildren().get(Oid.class); + assertThat(oid).isNotNull(); + assertThat(oid.getChildren()).isEmpty(); + assertThat(oid.asString()).isEqualTo("1.2.840.113549.1.1.10"); + + INode key = pss.getChildren().get(Key.class); + assertThat(key).isNotNull(); + assertThat(key.asString()).isEqualTo("RSA"); + assertThat(key.getChildren()).hasSize(2); + INode keyGen = key.getChildren().get(KeyGeneration.class); + assertThat(keyGen).isNotNull(); + assertThat(keyGen.getChildren()).isEmpty(); + assertThat(keyGen.asString()).isEqualTo("KEYGENERATION"); + INode pke = key.getChildren().get(PublicKeyEncryption.class); + assertThat(pke).isNotNull(); + INode pkeOid = pke.getChildren().get(Oid.class); + assertThat(pkeOid).isNotNull(); + assertThat(pkeOid.getChildren()).isEmpty(); + assertThat(pkeOid.asString()).isEqualTo("1.2.840.113549.1.1.1"); + + INode md = pss.getChildren().get(MessageDigest.class); + assertThat(md).isNotNull(); + assertThat(md.asString()).isEqualTo("SHA-256"); + assertThat(md.getChildren()).hasSize(4); + INode mdOid = md.getChildren().get(Oid.class); + assertThat(mdOid).isNotNull(); + assertThat(mdOid.getChildren()).isEmpty(); + assertThat(mdOid.asString()).isEqualTo("2.16.840.1.101.3.4.2.1"); + INode digestSize = md.getChildren().get(DigestSize.class); + assertThat(digestSize).isNotNull(); + assertThat(digestSize.getChildren()).isEmpty(); + assertThat(digestSize.asString()).isEqualTo("256"); + INode blockSize = md.getChildren().get(BlockSize.class); + assertThat(blockSize).isNotNull(); + assertThat(blockSize.getChildren()).isEmpty(); + assertThat(blockSize.asString()).isEqualTo("512"); + INode digest = md.getChildren().get(Digest.class); + assertThat(digest).isNotNull(); + assertThat(digest.getChildren()).isEmpty(); + assertThat(digest.asString()).isEqualTo("DIGEST"); + + INode verify = pss.getChildren().get(Verify.class); + assertThat(verify).isNotNull(); + assertThat(verify.getChildren()).isEmpty(); + assertThat(verify.asString()).isEqualTo("VERIFY"); + } + } +}