EdDSA initial and untested implementation, test suite refactor, and solving steganography import issues

This commit is contained in:
Nguyễn Đình Quý
2025-12-05 19:51:14 +07:00
parent 21c3eb827d
commit b5ea84835d
12 changed files with 969 additions and 601 deletions
+2 -1
View File
@@ -2,4 +2,5 @@
__pycache__/
src/__pycache__/
src/cryptography_primitives/__pycache__/
tests/__pycache__/
tests/__pycache__/
wip/
@@ -0,0 +1,394 @@
from cryptography.hazmat.primitives import asymmetric
from cryptography.hazmat.primitives import serialization
import base64
from cryptography.exceptions import InvalidSignature
class InitNode:
CATEGORY = "Cryptography/Modern/Asymmetric"
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
# Auto-set FUNCTION to lowercase class name
cls.FUNCTION = cls.__name__.lower()
class EdDSAPrivateKeyFormat(InitNode):
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"key_type": (
["Ed25519", "Ed448"],
{"default": "Ed25519", "description": "The key type to use for EdDSA-based asymmetric signing algorithms."},
),
"encoding_format": (
["PEM", "DER (Converted)", "OpenSSH", "Raw (Converted)", "X962 (Converted)", "SMIME"],
{
"default": "PEM",
"description": 'Encoding type for the private key. Some formats (ones with "(Converted)" next to them) are binary formats, which cannot be outputted normally in ComfyUI. To better serve the purpose of the node, these formats will be converted to a chosen format below in `conversion_format`.',
},
),
"conversion_format": (
["Base64", "Hexadecimal", "UTF-8 String", "Binary"],
{
"default": "Base64",
"description": "The conversion format to be used with the converted encoding format that cannot be outputted raw.",
},
),
"formatting": (
["Traditional OpenSSL", "PKCS8", "Raw (Converted)", "OpenSSH (Requires PEM)"],
{
"default": "OpenSSH (Requires PEM)",
"description": "What format to serialize the key in",
},
),
"encryption_algorithm": (["Best Available", "None"], {"default": "Best Available"}),
},
"optional": {
"encryption_password": (
"STRING",
{
"default": "",
"multiline": False,
"tooltip": "The password to use to encrypt the private key.",
},
),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("private_bytes",)
def from_private_key_formatting(self, encoding_format, formatting, encryption_algorithm, encryption_password):
if encoding_format in ["PEM", "OpenSSH", "SMIME"]:
encode = getattr(serialization.Encoding, encoding_format)
elif encoding_format == "DER (Converted)":
encode = serialization.Encoding.DER
elif encoding_format == "Raw (Converted)":
encode = serialization.Encoding.Raw
elif encoding_format == "X962 (Converted)":
encode = serialization.Encoding.X962
else:
raise ValueError
if formatting == "Traditional OpenSSL":
format = serialization.PrivateFormat.TraditionalOpenSSL
elif formatting == "PKCS8":
format = serialization.PrivateFormat.PKCS8
elif formatting == "Raw (Converted)":
format = serialization.PrivateFormat.Raw
elif formatting == "OpenSSH (Requires PEM)":
format = serialization.PrivateFormat.OpenSSH
else:
raise ValueError
if encryption_algorithm == "Best Available":
encryption_algorithm = serialization.BestAvailableEncryption(encryption_password.encode("utf-8"))
elif encryption_algorithm == "None":
encryption_algorithm = serialization.NoEncryption()
else:
raise ValueError
return (encode, format, encryption_algorithm)
def eddsaprivatekeyformat(self, key_type, encoding_format, formatting, encryption_algorithm, conversion_format, encryption_password):
if key_type == "Ed25519":
ed = asymmetric.ed25519.Ed25519PrivateKey
elif key_type == "Ed448":
ed = asymmetric.ed448.Ed448PrivateKey
else:
raise ValueError
ed_private_key = ed.generate()
output = ed_private_key.private_bytes(
self.from_private_key_formatting(encoding_format, formatting, encryption_algorithm, encryption_password)
)
if encoding_format in ["DER (Converted)", "Raw (Converted)", "X962 (Converted)"]:
output = output.decode("utf-8")
if conversion_format == "Base64":
output = base64.b64encode(output).decode("utf-8")
elif conversion_format == "Hexadecimal":
output = output.hex()
elif conversion_format == "UTF-8 String":
output = output.decode("utf-8")
elif conversion_format == "Binary":
output = bytes(int(b, 2) for b in output.split(" ")).decode("utf-8")
else:
raise ValueError
return (output,)
class EdDSASignature(InitNode):
CATEGORY = "Cryptography/Modern/Asymmetric"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"key_source": (
"BOOLEAN",
{
"label_on": "Fresh Key",
"label_off": "From Private Bytes",
"tooltip": "The source of the private key to be used to sign the message",
},
),
"key_type": (
["Ed25519", "Ed448"],
{"default": "Ed25519", "description": "The key type to use for EdDSA-based asymmetric signing algorithms."},
),
"message": (
"STRING",
{
"default": "Hello World!",
"multiline": True,
"placeholder": "Type your message here...",
},
),
},
"optional": {
"private_bytes": (
"STRING",
{
"default": "",
"multiline": True,
"tooltip": "Only applicable if key_source is set to From Private Bytes. Uses the format defined below.",
},
),
"byte_format": (["Base64", "Hexadecimal", "String", "Binary"], {}),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("signature",)
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
# Auto-set FUNCTION to lowercase class name
cls.FUNCTION = cls.__name__.lower()
def EdDSAInit(self, key_source, key_type, private_bytes, byte_format):
if key_type == "Ed25519":
ed = asymmetric.ed25519.Ed25519PrivateKey
elif key_type == "Ed448":
ed = asymmetric.ed448.Ed448PrivateKey
else:
raise ValueError
if key_source:
ed_private_key = ed.generate()
else:
if byte_format == "Base64":
ed_private_bytes = base64.b64decode(private_bytes).encode("utf-8")
elif byte_format == "Hexadecimal":
ed_private_bytes = bytes.fromhex(private_bytes)
elif byte_format == "String":
ed_private_bytes = private_bytes.encode("utf-8")
elif byte_format == "Binary":
ed_private_bytes = bytes(int(b, 2) for b in private_bytes.split(" "))
else:
raise ValueError
ed_private_key = ed.from_private_bytes(ed_private_bytes)
return ed_private_key
def edssasignature(self, key_source, key_type, message, private_bytes, byte_format):
signature = self.EdDSAInit(key_source, key_type, private_bytes, byte_format).sign(message.encode("utf-8"))
return (signature.hex(),)
class EdDSAPublicKeyFormat(InitNode):
CATEGORY = "Cryptography/Modern/Asymmetric"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"key_source": (
"BOOLEAN",
{
"label_on": "Fresh Key",
"label_off": "From Private Bytes",
"tooltip": "The source of the private key to be used to generate the public key.",
},
),
"key_type": (
["Ed25519", "Ed448"],
{"default": "Ed25519", "description": "The key type to use for EdDSA-based asymmetric signing algorithms."},
),
"encoding_format": (
["PEM", "DER (Converted)", "OpenSSH", "Raw (Converted)", "X962 (Converted)", "SMIME"],
{
"default": "PEM",
"description": 'Encoding type for the private key. Some formats (ones with "(Converted)" next to them) are binary formats, which cannot be outputted normally in ComfyUI. To better serve the purpose of the node, these formats will be converted to a chosen format below in `conversion_format`.',
},
),
"conversion_format": (
["Base64", "Hexadecimal", "UTF-8 String", "Binary"],
{
"default": "Base64",
"description": "The conversion format to be used with the converted encoding format that cannot be outputted raw.",
},
),
"formatting": (
["SubjectPublicKeyInfo", "PKCS8", "Raw (Converted)", "OpenSSH (Requires PEM)"],
{
"default": "OpenSSH (Requires PEM)",
"description": "What format to serialize the key in",
},
),
},
"optional": {
"private_bytes": (
"STRING",
{
"default": "",
"multiline": True,
"tooltip": "Only applicable if key_source is set to From Private Bytes. Uses the format defined below.",
},
),
"byte_format": (["Base64", "Hexadecimal", "String", "Binary"], {}),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("public_bytes",)
def from_public_key_formatting(self, encoding_format, formatting):
if encoding_format in ["PEM", "OpenSSH", "SMIME"]:
encode = getattr(serialization.Encoding, encoding_format)
elif encoding_format == "DER (Converted)":
encode = serialization.Encoding.DER
elif encoding_format == "Raw (Converted)":
encode = serialization.Encoding.Raw
elif encoding_format == "X962 (Converted)":
encode = serialization.Encoding.X962
else:
raise ValueError
if formatting == "SubjectPublicKeyInfo":
format = serialization.PublicFormat.SubjectPublicKeyInfo
elif formatting == "PKCS8":
format = serialization.PublicFormat.PKCS8
elif formatting == "Raw (Converted)":
format = serialization.PublicFormat.Raw
elif formatting == "OpenSSH (Requires PEM)":
format = serialization.PublicFormat.OpenSSH
else:
raise ValueError
return (encode, format)
def eddsapublickeyformat(self, key_source, key_type, encoding_format, conversion_format, formatting, private_bytes, byte_format):
ed_private_key = EdDSASignature.EdDSAInit(key_source, key_type, private_bytes, byte_format)
ed_public_key = ed_private_key.public_key()
output = ed_public_key.public_bytes(self.from_public_key_formatting(encoding_format, formatting))
if encoding_format in ["DER (Converted)", "Raw (Converted)", "X962 (Converted)"]:
output = output.decode("utf-8")
if conversion_format == "Base64":
output = base64.b64encode(output).decode("utf-8")
elif conversion_format == "Hexadecimal":
output = output.hex()
elif conversion_format == "UTF-8 String":
output = output.decode("utf-8")
elif conversion_format == "Binary":
output = bytes(int(b, 2) for b in output.split(" ")).decode("utf-8")
else:
raise ValueError
return (output,)
class EdDSAVerify(InitNode):
CATEGORY = "Cryptography/Modern/Asymmetric"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"key_source": (
"BOOLEAN",
{
"label_on": "Fresh Key",
"label_off": "From Public Bytes",
"tooltip": "The source of the public key to be used to verify the message",
},
),
"key_type": (
["Ed25519", "Ed448"],
{"default": "Ed25519", "description": "The key type to use for EdDSA-based asymmetric signing algorithms."},
),
"message": (
"STRING",
{
"default": "Hello World!",
"multiline": True,
"placeholder": "Type your message here...",
},
),
"signature": (
"STRING",
{
"default": "",
"multiline": True,
"placeholder": "Type your signature here... (in hexadecimal)",
},
),
},
"optional": {
"public_bytes": (
"STRING",
{
"default": "",
"multiline": True,
"tooltip": "Only applicable if key_source is set to From Private Bytes. Uses the format defined below.",
},
),
"byte_format": (["Base64", "Hexadecimal", "String", "Binary"], {}),
},
}
RETURN_TYPES = ("BOOLEAN",)
RETURN_NAMES = ("verify_status",)
def eddsaverify(self, key_source, key_type, message, signature, public_bytes, byte_format):
if key_type == "Ed25519":
ed = asymmetric.ed25519.Ed25519PrivateKey
elif key_type == "Ed448":
ed = asymmetric.ed448.Ed448PrivateKey
else:
raise ValueError
if key_source:
ed_private_key = ed.generate()
ed_public_key = ed_private_key.public_key()
elif not key_source:
if byte_format == "Base64":
ed_public_bytes = base64.b64decode(public_bytes).encode("utf-8")
elif byte_format == "Hexadecimal":
ed_public_bytes = bytes.fromhex(public_bytes)
elif byte_format == "String":
ed_public_bytes = public_bytes.encode("utf-8")
elif byte_format == "Binary":
ed_public_bytes = bytes(int(b, 2) for b in public_bytes.split(" "))
else:
raise ValueError
ed_public_key = ed.from_public_bytes(ed_public_bytes)
decoded_signature = bytes.fromhex(signature)
try:
ed_public_key.verify(decoded_signature, message)
output = True
except InvalidSignature:
output = False
return (output,)
NODE_CLASS_MAPPINGS = {
"EdDSAPrivateKeyFormat": EdDSAPrivateKeyFormat,
"EdDSASignature": EdDSASignature,
"EdDSAPublicKeyFormat": EdDSAPublicKeyFormat,
"EdDSAVerify": EdDSAVerify,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"EdDSAPrivateKeyFormat": "EdDSA Private Key Bytes",
"EdDSASignature": "EdDSA Signature Generator",
"EdDSAPublicKeyFormat": "EdDSA Public Key Bytes",
"EdDSAVerify": "EDDSA Message Verification",
}
+15 -1
View File
@@ -1,4 +1,5 @@
import os
import sys
import inspect
import textwrap
@@ -8,7 +9,20 @@ import torch
from PIL import Image
import numpy as np
import folder_paths # This is dealt with by ComfyUI. If this import is throwing an error, ignore it.
# folder_path.py solver, just so the complaints will stop.
current = os.path.dirname(os.path.realpath(__file__))
while True:
candidate = os.path.join(current, "folder_paths.py")
if os.path.exists(candidate):
target_dir = current
break
parent = os.path.dirname(current)
if parent == current:
raise FileNotFoundError("folder_paths.py not found in any parent directories")
current = parent
sys.path.insert(0, target_dir)
import folder_paths # This import is handled by the solver above looking for it inside the parent directories. This will most likely hit the one from base ComfyUI, assuming no other nodes or .py file carry this namespace.
# Every node is inspired heavily by their reference implementations in their GitHub repository, with changes made to best use PyTorch as possible as it's the main way ComfyUI stores data
# For more information, check https://docs.comfy.org/custom-nodes/backend/images_and_masks#images
+57 -87
View File
@@ -100,61 +100,34 @@ class ConverterNodes:
class String2Binary(ConverterNodes):
def string2binary(self, text, encoding_format, other_encoding_format):
return (
" ".join(
format(c, "b")
for c in bytearray(
text, self.encoding_selector(encoding_format, other_encoding_format)
)
),
)
return (" ".join(format(c, "b") for c in bytearray(text, self.encoding_selector(encoding_format, other_encoding_format))),)
class Binary2String(ConverterNodes):
def binary2string(self, text, encoding_format, other_encoding_format):
return (
bytes(int(b, 2) for b in text.split(" ")).decode(
self.encoding_selector(encoding_format, other_encoding_format)
),
)
return (bytes(int(b, 2) for b in text.split(" ")).decode(self.encoding_selector(encoding_format, other_encoding_format)),)
class String2Hex(ConverterNodes):
def string2hex(self, text, encoding_format, other_encoding_format):
return (
text.encode(
self.encoding_selector(encoding_format, other_encoding_format)
).hex(),
)
return (text.encode(self.encoding_selector(encoding_format, other_encoding_format)).hex(),)
class Hex2String(ConverterNodes):
def hex2string(self, text, encoding_format, other_encoding_format):
return (
bytes.fromhex(text.replace("0x", "").replace(" ", "")).decode(
self.encoding_selector(encoding_format, other_encoding_format)
),
bytes.fromhex(text.replace("0x", "").replace(" ", "")).decode(self.encoding_selector(encoding_format, other_encoding_format)),
)
class String2Base64(ConverterNodes):
def string2base64(self, text, encoding_format, other_encoding_format):
return (
base64.b64encode(
text.encode(
self.encoding_selector(encoding_format, other_encoding_format)
)
).decode("ascii"),
)
return (base64.b64encode(text.encode(self.encoding_selector(encoding_format, other_encoding_format))).decode("ascii"),)
class Base642String(ConverterNodes):
def base642string(self, text, encoding_format, other_encoding_format):
return (
base64.b64decode(text.encode("ascii")).decode(
self.encoding_selector(encoding_format, other_encoding_format)
),
)
return (base64.b64decode(text.encode("ascii")).decode(self.encoding_selector(encoding_format, other_encoding_format)),)
# The Bitwise category of Utilities. Also has auto-detection for the sake of my sanity.
@@ -241,17 +214,13 @@ class BitwiseNodes:
if len(cleaned) % 8 != 0:
# pad to nearest byte
cleaned = cleaned.zfill(((len(cleaned) + 7) // 8) * 8)
return bytes(
int(cleaned[i : i + 8], 2) for i in range(0, len(cleaned), 8)
), "Binary"
return bytes(int(cleaned[i : i + 8], 2) for i in range(0, len(cleaned), 8)), "Binary"
# Leading 0 + digits 0/1 → implicit binary
elif text.startswith("0") and all(c in "01" for c in text):
# pad to nearest byte
cleaned = text.zfill(((len(text) + 7) // 8) * 8)
return bytes(
int(cleaned[i : i + 8], 2) for i in range(0, len(cleaned), 8)
), "Binary"
return bytes(int(cleaned[i : i + 8], 2) for i in range(0, len(cleaned), 8)), "Binary"
# Integer detection
elif text.isdigit(): # simple positive integer
@@ -277,25 +246,17 @@ class BitwiseNodes:
# Default to chosen formatted string
else:
return text.encode(
self.encoding_selector(encoding_format, other_encoding_format)
), "String"
return text.encode(self.encoding_selector(encoding_format, other_encoding_format)), "String"
def operate(
self, text_1, text_2, encoding_format, other_encoding_format=None, func=None
):
def operate(self, text_1, text_2, encoding_format, other_encoding_format=None, func=None):
"""
func: a callable that takes one or two byte objects and returns bytes
Returns: (result_bytes, detected_format_of_input1)
"""
b1, return_fmt = self.detect_and_parse(
text_1, encoding_format, other_encoding_format
)
b1, return_fmt = self.detect_and_parse(text_1, encoding_format, other_encoding_format)
if text_2 is not None:
b2, _ = self.detect_and_parse(
text_2, encoding_format, other_encoding_format
)
b2, _ = self.detect_and_parse(text_2, encoding_format, other_encoding_format)
# Ensure same length for operations that need it
if len(b1) != len(b2):
raise ValueError("Inputs must be same length for bitwise operations")
@@ -305,9 +266,7 @@ class BitwiseNodes:
return result, return_fmt
def format_output(
self, data, output_format, encoding_format, other_encoding_format=None
):
def format_output(self, data, output_format, encoding_format, other_encoding_format=None):
if output_format == "Binary":
return " ".join(format(b, "08b") for b in data)
elif output_format == "Hex":
@@ -317,9 +276,7 @@ class BitwiseNodes:
elif output_format == "Int":
return str(int.from_bytes(data, "big"))
elif output_format == "String":
return data.decode(
self.encoding_selector(encoding_format, other_encoding_format)
)
return data.decode(self.encoding_selector(encoding_format, other_encoding_format))
else:
raise ValueError(f"Unknown output format {output_format}")
@@ -333,11 +290,7 @@ class BitwiseAND(BitwiseNodes):
other_encoding_format,
func=lambda b1, b2: bytes(x & y for x, y in zip(b1, b2)),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class BitwiseOR(BitwiseNodes):
@@ -349,11 +302,7 @@ class BitwiseOR(BitwiseNodes):
other_encoding_format,
func=lambda b1, b2: bytes(x | y for x, y in zip(b1, b2)),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class BitwiseNOT(BitwiseNodes):
@@ -372,11 +321,7 @@ class BitwiseNOT(BitwiseNodes):
other_encoding_format,
func=lambda b1: bytes((~x & 0xFF) for x in b1),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class BitwiseXOR(BitwiseNodes):
@@ -388,11 +333,7 @@ class BitwiseXOR(BitwiseNodes):
other_encoding_format,
func=lambda b1, b2: bytes(x ^ y for x, y in zip(b1, b2)),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class BitwiseLS(BitwiseNodes):
@@ -404,11 +345,7 @@ class BitwiseLS(BitwiseNodes):
other_encoding_format,
func=lambda b1, b2: bytes(x << y for x, y in zip(b1, b2)),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class BitwiseRS(BitwiseNodes):
@@ -420,11 +357,42 @@ class BitwiseRS(BitwiseNodes):
other_encoding_format,
func=lambda b1, b2: bytes(x >> y for x, y in zip(b1, b2)),
)
return (
self.format_output(
result_bytes, input_format, encoding_format, other_encoding_format
),
)
return (self.format_output(result_bytes, input_format, encoding_format, other_encoding_format),)
class StringLooper:
CATEGORY = "Utilities/Padding"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": (
"STRING",
{
"default": "Hello World!",
"multiline": True,
"placeholder": "Type your message here...",
},
),
"loops": (
"INT",
{
"min": 1,
"step": 1,
"default": 3,
"tooltip": "The number of times to repeat the string given",
},
),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("looped_text",)
FUNCTION = "Looper"
def Looper(self, text=str, loops=int):
return (text * (loops + 1),)
# A dictionary that contains all nodes you want to export with their names
@@ -443,6 +411,7 @@ NODE_CLASS_MAPPINGS = {
"BitwiseXOR": BitwiseXOR,
"BitwiseLS": BitwiseLS,
"BitwiseRS": BitwiseRS,
"StringLooper": StringLooper,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -459,4 +428,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"BitwiseXOR": "Bitwise XOR Operator",
"BitwiseLS": "Bitwise Left Shift Operator",
"BitwiseRS": "Bitwise Right Shift Operator",
"StringLooper": "String Append Looper",
}
+1
View File
@@ -0,0 +1 @@
# This file makes the tests/nodes directory a Python package.
+33
View File
@@ -0,0 +1,33 @@
from src.comfyui_arg_toolkit.cryptography_primitives import auth_encrypt
# Test suite for auth_encrypt.py
class TestAuthEncrypt:
def test_chacha20poly1305(self):
chacha20poly1305 = auth_encrypt.ChaCha20Poly1305()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = chacha20poly1305.cc20(text, key, nonce, associated_data, True)
decrypted_text = chacha20poly1305.cc20(encrypted_text[0], key, nonce, associated_data, False)
assert decrypted_text[0] == text
def test_aes_gcm(self):
aes_gcm = auth_encrypt.AESAuth()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = aes_gcm.aesauth(text, key, nonce, associated_data, True, "AES-GCM", 16)
decrypted_text = aes_gcm.aesauth(encrypted_text[0], key, nonce, associated_data, False, "AES-GCM", 16)
assert decrypted_text[0] == text
def test_aes_ccm(self):
aes_ccm = auth_encrypt.AESAuth()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = aes_ccm.aesauth(text, key, nonce, associated_data, True, "AES-CCM", 16)
decrypted_text = aes_ccm.aesauth(encrypted_text[0], key, nonce, associated_data, False, "AES-CCM", 16)
assert decrypted_text[0] == text
+142
View File
@@ -0,0 +1,142 @@
from src.comfyui_arg_toolkit import ciphers
# Test suite for ciphers.py
class TestCiphers:
def test_atbash_cipher(self):
atbash_cipher = ciphers.Atbash()
text = "Hello World"
alphabet = "ENGLISH"
encrypted_text = atbash_cipher.atbash(text, alphabet, True, False)
decrypted_text = atbash_cipher.atbash(encrypted_text[0], alphabet, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_caesar_cipher(self):
caesar_cipher = ciphers.Caesar()
text = "Hello World"
alphabet = "ENGLISH"
key = 3
encrypted_text = caesar_cipher.caesar(text, alphabet, key, True, False)
decrypted_text = caesar_cipher.caesar(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_vigenere_cipher(self):
vigenere_cipher = ciphers.Vigenere()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = vigenere_cipher.vigenere(text, alphabet, key, True, False)
decrypted_text = vigenere_cipher.vigenere(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_adfgx_cipher(self):
adfgx_cipher = ciphers.ADFGX()
text = "HelloWorld"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key = "KEY"
encrypted_text = adfgx_cipher.adfgx(text, alphabet, key, True, False)
decrypted_text = adfgx_cipher.adfgx(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower()
def test_autokey_cipher(self):
autokey_cipher = ciphers.Autokey()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = autokey_cipher.autokey(text, alphabet, key, True, False)
decrypted_text = autokey_cipher.autokey(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_beaufort_cipher(self):
beaufort_cipher = ciphers.Beaufort()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = beaufort_cipher.beaufort(text, alphabet, key, True, False)
decrypted_text = beaufort_cipher.beaufort(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_caesarprog_cipher(self):
caesarprogessive_cipher = ciphers.CaesarProgressive()
text = "Hello World"
alphabet = "ENGLISH"
key = 3
encrypted_text = caesarprogessive_cipher.caesarprogressive(text, alphabet, key, True, False)
decrypted_text = caesarprogessive_cipher.caesarprogressive(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_rot13_cipher(self):
rot13_cipher = ciphers.Rot13()
text = "Hello World"
alphabet = "ENGLISH"
encrypted_text = rot13_cipher.rot13(text, alphabet, 13, True, False)
decrypted_text = rot13_cipher.rot13(encrypted_text[0], alphabet, 13, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_scytale_cipher(self):
scytale_cipher = ciphers.Scytale()
text = "Hello World"
alphabet = "ENGLISH"
key = 4
encrypted_text = scytale_cipher.scytale(text, alphabet, key, True, False)
decrypted_text = scytale_cipher.scytale(encrypted_text[0], alphabet, key, False, False)
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_playfair_cipher(self):
playfair_cipher = ciphers.Playfair()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key = "KEYWORD"
encrypted_text = playfair_cipher.playfair(text, alphabet, key, True, False)
decrypted_text = playfair_cipher.playfair(encrypted_text[0], alphabet, key, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_foursquare_cipher(self):
foursquare_cipher = ciphers.FourSquare()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key_1 = "KEYONE"
key_2 = "KEYTWO"
encrypted_text = foursquare_cipher.foursquare(text, alphabet, key_1, key_2, True, False)
decrypted_text = foursquare_cipher.foursquare(encrypted_text[0], alphabet, key_1, key_2, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_twosquare_cipher(self):
twosquare_cipher = ciphers.TwoSquare()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key_1 = "KEYONE"
key_2 = "KEYTWO"
encrypted_text = twosquare_cipher.twosquare(text, alphabet, key_1, key_2, True, False)
decrypted_text = twosquare_cipher.twosquare(encrypted_text[0], alphabet, key_1, key_2, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_gronsfeld_cipher(self):
gronsfeld_cipher = ciphers.Gronsfeld()
text = "Hello World"
alphabet = "ENGLISH"
key = "1337"
encrypted_text = gronsfeld_cipher.gronsfeld(text, alphabet, key, True, False)
decrypted_text = gronsfeld_cipher.gronsfeld(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_trifid_cipher(self):
trifid_cipher = ciphers.Trifid()
text = "HelloWorld"
# Trifid in secretpy uses a 27-char alphabet (letters + separator)
alphabet = "abcdefghijklmnopqrstuvwxyz."
key = 5 # period
encrypted_text = trifid_cipher.trifid(text, alphabet, key, True, False)
decrypted_text = trifid_cipher.trifid(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower()
def test_zigzag_cipher(self):
zigzag_cipher = ciphers.Zigzag()
text = "Hello World"
key = 4 # rails
# The node wrapper for Zigzag doesn't use an alphabet, it's a pure transposition
encrypted_text = zigzag_cipher.zigzag(text, key, True, False)
decrypted_text = zigzag_cipher.zigzag(encrypted_text[0], key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
+128
View File
@@ -0,0 +1,128 @@
from src.comfyui_arg_toolkit.cryptography_primitives import const_time
from src.comfyui_arg_toolkit.cryptography_primitives import kdf
from src.comfyui_arg_toolkit.cryptography_primitives import key_wrapper
from src.comfyui_arg_toolkit.cryptography_primitives import symm_padding
from src.comfyui_arg_toolkit.cryptography_primitives import symmetrical_encrypt
class TestConstantTimeCompare:
def test_compare_equal(self):
compare = const_time.ConstantTimeCompare()
a = "deadbeef"
b = "deadbeef"
result = compare.compare(a, b)
assert result[0] is True
def test_compare_not_equal(self):
compare = const_time.ConstantTimeCompare()
a = "deadbeef"
b = "cafebabe"
result = compare.compare(a, b)
assert result[0] is False
class TestKeyDerivation:
def test_argon2id_derive_verify(self):
derive = kdf.Argon2id_Derive()
verify = kdf.Argon2id_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.argon2id_derive(message, 32, salt, 1, 4, 65536, "", "", True)
verified = verify.argon2id_verify(message, 32, salt, 1, 4, 65536, "", "", True, derived_key[0])
assert verified[0] is True
def test_pbkdf2hmac_derive_verify(self):
derive = kdf.PBKDF2HMAC_Derive()
verify = kdf.PBKDF2HMAC_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.pbkdf2hmac_derive(message, 32, salt, 1000, "SHA256")
verified = verify.pbkdf2hmac_verify(message, 32, salt, 1000, "SHA256", derived_key[0])
assert verified[0] is True
def test_scrypt_derive_verify(self):
derive = kdf.Scrypt_Derive()
verify = kdf.Scrypt_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.scrypt_derive(message, 32, salt, 14, 8, 1)
verified = verify.scrypt_verify(message, 32, salt, 14, 8, 1, derived_key[0])
assert verified[0] is True
class TestKeyWrapper:
def test_aeskeywrap(self):
wrapper = key_wrapper.AESKeyWrap()
wrapping_key = "00" * 32
key_to_wrap = "11" * 16
wrapped_key = wrapper.aeskeywrap(wrapping_key, key_to_wrap, True)
unwrapped_key = wrapper.aeskeywrap(wrapping_key, wrapped_key[0], False)
assert unwrapped_key[0] == key_to_wrap
def test_aeskeywrapwithpadding(self):
wrapper = key_wrapper.AESKeyWrapWithPadding()
wrapping_key = "00" * 32
key_to_wrap = "11" * 20 # Not a multiple of 8
wrapped_key = wrapper.aeskeywrapwithpadding(wrapping_key, key_to_wrap, True)
unwrapped_key = wrapper.aeskeywrapwithpadding(wrapping_key, wrapped_key[0], False)
assert unwrapped_key[0] == key_to_wrap
class TestSymmetricalPadding:
def test_pkcs7_padding(self):
padding_node = symm_padding.PaddingNode()
data = "Hello World"
padded_data = padding_node.padding(data, 128, "PKCS7", True)
unpadded_data = padding_node.padding(padded_data[0], 128, "PKCS7", False)
assert unpadded_data[0] == data
def test_ansix923_padding(self):
padding_node = symm_padding.PaddingNode()
data = "Hello World"
padded_data = padding_node.padding(data, 128, "ANSIX923", True)
unpadded_data = padding_node.padding(padded_data[0], 128, "ANSIX923", False)
assert unpadded_data[0] == data
class TestSymmetricalEncryption:
def test_aes_cbc_encryption_decryption(self):
enc_dec = symmetrical_encrypt.EncryptDecrypt()
text = "Hello World"
key = "00" * 32
iv = "11" * 16
# Pad the text first
padding_node = symm_padding.PaddingNode()
padded_text = padding_node.padding(text, 128, "PKCS7", True)
encrypted_text = enc_dec.encryptdecrypt(padded_text[0], key, iv, "", "AES", "CBC", True, 16, "")
decrypted_text_hex = enc_dec.encryptdecrypt(encrypted_text[0], key, iv, "", "AES", "CBC", False, 16, "")
print(f"Type: {type(decrypted_text_hex[0])}")
print(f"Value: {repr(decrypted_text_hex[0])}")
# Unpad the decrypted text
unpadded_data = padding_node.padding(decrypted_text_hex[0], 128, "PKCS7", False)
assert unpadded_data[0] == text
+58
View File
@@ -0,0 +1,58 @@
from src.comfyui_arg_toolkit.cryptography_primitives import hashing
# Test suite for hashing.py
class TestHashing:
def test_sha256(self):
sha256 = hashing.SHA2()
text = "Hello World"
hashed_text = (sha256.sha2(key1=text, algorithm="SHA256"),)
assert hashed_text[0][0] == "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
def test_blake2b(self):
blake2b = hashing.BLAKE2()
text = "Hello World"
hashed_text = blake2b.blake2(key1=text, algorithm="BLAKE2b", digest_size=64)
assert (
hashed_text[0]
== "4386a08a265111c9896f56456e2cb61a64239115c4784cf438e36cc851221972da3fb0115f73cd02486254001f878ab1fd126aac69844ef1c1ca152379d0a9bd"
)
def test_sha3_256(self):
sha3_256 = hashing.SHA3()
text = "Hello World"
hashed_text = (sha3_256.sha3(key1=text, algorithm="SHA3_256"),)
assert hashed_text[0][0] == "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51"
def test_sha1(self):
sha1 = hashing.SHA1()
text = "Hello World"
hashed_text = (sha1.sha1(key1=text, algorithm=None),)
assert hashed_text[0][0] == "0a4d55a8d778e5022fab701977c5d840bbc486d0"
def test_md5(self):
md5 = hashing.MD5()
text = "Hello World"
hashed_text = (md5.md5(key1=text, algorithm=None),)
assert hashed_text[0][0] == "b10a8db164e0754105b7a99be72e3fe5"
def test_sm3(self):
sm3 = hashing.SM3()
text = "Hello World"
hashed_text = (sm3.sm3(key1=text, algorithm=None),)
assert hashed_text[0][0] == "77015816143ee627f4fa410b6dad2bdb9fcbdf1e061a452a686b8711a484c5d7"
def test_shake128(self):
shake128 = hashing.SHAKE()
text = "Hello World"
hashed_text = shake128.shake(
key1=text,
algorithm="SHAKE128",
output_length=32,
digest_size=64,
squeeze_bytes=16,
squeeze_times=2,
)
assert (
hashed_text[0][0]
== "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e2"
)
+61
View File
@@ -0,0 +1,61 @@
import unicodedata
from src.comfyui_arg_toolkit import morse_code
# Test suite for morse_code.py
class TestMorseCode:
def setup_method(self):
self.morse_code = morse_code.MorseCode()
def test_latin_morse_code(self):
text = "Hello World"
encoded_text = self.morse_code.MorseCode(text, True, "latin", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "latin", ".", "-")
assert decoded_text[0].lower() == text.lower()
def test_russian_morse_code(self):
text = "Привет мир"
encoded_text = self.morse_code.MorseCode(text, True, "russian", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "russian", ".", "-")
assert decoded_text[0].lower() == text.lower()
def test_arabic_morse_code(self):
text = "مرحبا بالعالم"
encoded_text = self.morse_code.MorseCode(text, True, "arabic", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "arabic", ".", "-")
assert decoded_text[0] == text
def test_hebrew_morse_code(self):
text = "שלום עולם"
encoded_text = self.morse_code.MorseCode(text, True, "hebrew", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "hebrew", ".", "-")
assert decoded_text[0] == "שלומ עולמ"
def test_greek_morse_code(self):
text = "Γειά σου Κόσμε"
encoded_text = self.morse_code.MorseCode(text, True, "greek", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "greek", ".", "-")
assert decoded_text[0] == "ΓΕΙΑ ΣΟΥ ΚΟΣΜΕ"
def test_korean_morse_code(self):
text = "안녕하세요"
encoded_text = self.morse_code.MorseCode(text, True, "korean", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "korean", ".", "-")
assert decoded_text[0] == "ㅇㅏㄴㄴㅕㅇㅎㅏㅅㅔㅇㅛ"
def test_japanese_wabun_morse_code(self):
text = "こんにちは"
normalized_text = unicodedata.normalize("NFKC", text)
print(f"Normalized text: {normalized_text}")
encoded_text = self.morse_code.MorseCode(text, True, "japanese-wabun", ".", "-")
print(f"Encoded text: {encoded_text}")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "japanese-wabun", ".", "-")
print(f"Decoded text: {decoded_text}")
assert decoded_text == ("コンニチハ",)
def test_custom_dot_dash_morse_code(self):
text = "Hello World"
dot = "1"
dash = "0"
encoded_text = self.morse_code.MorseCode(text, True, "latin", dot, dash)
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "latin", dot, dash)
assert decoded_text[0].lower() == text.lower()
+78
View File
@@ -0,0 +1,78 @@
from src.comfyui_arg_toolkit import utils
# Test suite for utils.py
class TestUtils:
# Converters
def test_string_to_binary(self):
string_to_binary = utils.String2Binary()
text = "Hello World"
encoding = "utf-8"
binary_text = string_to_binary.string2binary(text, encoding, "")
assert binary_text[0] == "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
def test_binary_to_string(self):
binary_to_string = utils.Binary2String()
binary_text = "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
encoding = "utf-8"
text = binary_to_string.binary2string(binary_text, encoding, "")
assert text[0] == "Hello World"
def test_string_to_hex(self):
string_to_hex = utils.String2Hex()
text = "Hello World"
encoding = "utf-8"
hex_text = string_to_hex.string2hex(text, encoding, "")
assert hex_text[0] == "48656c6c6f20576f726c64"
def test_hex_to_string(self):
hex_to_string = utils.Hex2String()
hex_text = "48656c6c6f20576f726c64"
encoding = "utf-8"
text = hex_to_string.hex2string(hex_text, encoding, "")
assert text[0] == "Hello World"
def test_string_to_base64(self):
string_to_base64 = utils.String2Base64()
text = "Hello World"
encoding = "utf-8"
base64_text = string_to_base64.string2base64(text, encoding, "")
assert base64_text[0] == "SGVsbG8gV29ybGQ="
def test_base64_to_string(self):
base64_to_string = utils.Base642String()
base64_text = "SGVsbG8gV29ybGQ="
encoding = "utf-8"
text = base64_to_string.base642string(base64_text, encoding, "")
assert text[0] == "Hello World"
# Bitwise Operators
def test_bitwise_and(self):
bitwise_and = utils.BitwiseAND()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_and.bitwiseand(text1, text2, encoding, "")
assert result[0] == "6065606c64"
def test_bitwise_or(self):
bitwise_or = utils.BitwiseOR()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_or.bitwiseor(text1, text2, encoding, "")
assert result[0] == "7f6f7e6c6f"
def test_bitwise_xor(self):
bitwise_xor = utils.BitwiseXOR()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_xor.bitwisexor(text1, text2, encoding, "")
assert result[0] == "1f0a1e000b"
def test_bitwise_not(self):
bitwise_not = utils.BitwiseNOT()
text = "68656c6c6f"
encoding = "utf-8"
result = bitwise_not.bitwisenot(text, encoding, "")
assert result[0] == "979a939390"
-512
View File
@@ -1,512 +0,0 @@
import unicodedata
from src.comfyui_arg_toolkit import ciphers
from src.comfyui_arg_toolkit import utils
from src.comfyui_arg_toolkit.cryptography_primitives import auth_encrypt
from src.comfyui_arg_toolkit.cryptography_primitives import hashing
from src.comfyui_arg_toolkit import morse_code
# The entire test suite is designed to be as close to what a regular user would input into the nodes. This means that, for the most part, the test suite will not attempt to test for every edge cases, but rather to test for the most common use cases.
# For the most part, the test suite will not attempt to test for every edge cases, but rather to test for the most common use cases.
# For more information on how the test suite is designed, please refer to the README.md file.
# Test suite for ciphers.py
class TestCiphers:
def test_atbash_cipher(self):
atbash_cipher = ciphers.Atbash()
text = "Hello World"
alphabet = "ENGLISH"
encrypted_text = atbash_cipher.atbash(text, alphabet, True, False)
decrypted_text = atbash_cipher.atbash(encrypted_text[0], alphabet, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_caesar_cipher(self):
caesar_cipher = ciphers.Caesar()
text = "Hello World"
alphabet = "ENGLISH"
key = 3
encrypted_text = caesar_cipher.caesar(text, alphabet, key, True, False)
decrypted_text = caesar_cipher.caesar(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_vigenere_cipher(self):
vigenere_cipher = ciphers.Vigenere()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = vigenere_cipher.vigenere(text, alphabet, key, True, False)
decrypted_text = vigenere_cipher.vigenere(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_adfgx_cipher(self):
adfgx_cipher = ciphers.ADFGX()
text = "HelloWorld"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key = "KEY"
encrypted_text = adfgx_cipher.adfgx(text, alphabet, key, True, False)
decrypted_text = adfgx_cipher.adfgx(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower()
def test_autokey_cipher(self):
autokey_cipher = ciphers.Autokey()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = autokey_cipher.autokey(text, alphabet, key, True, False)
decrypted_text = autokey_cipher.autokey(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_beaufort_cipher(self):
beaufort_cipher = ciphers.Beaufort()
text = "Hello World"
alphabet = "ENGLISH"
key = "KEY"
encrypted_text = beaufort_cipher.beaufort(text, alphabet, key, True, False)
decrypted_text = beaufort_cipher.beaufort(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_caesarprog_cipher(self):
caesarprogessive_cipher = ciphers.CaesarProgressive()
text = "Hello World"
alphabet = "ENGLISH"
key = 3
encrypted_text = caesarprogessive_cipher.caesarprogressive(text, alphabet, key, True, False)
decrypted_text = caesarprogessive_cipher.caesarprogressive(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_rot13_cipher(self):
rot13_cipher = ciphers.Rot13()
text = "Hello World"
alphabet = "ENGLISH"
encrypted_text = rot13_cipher.rot13(text, alphabet, 13, True, False)
decrypted_text = rot13_cipher.rot13(encrypted_text[0], alphabet, 13, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_scytale_cipher(self):
scytale_cipher = ciphers.Scytale()
text = "Hello World"
alphabet = "ENGLISH"
key = 4
encrypted_text = scytale_cipher.scytale(text, alphabet, key, True, False)
decrypted_text = scytale_cipher.scytale(encrypted_text[0], alphabet, key, False, False)
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_playfair_cipher(self):
playfair_cipher = ciphers.Playfair()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key = "KEYWORD"
encrypted_text = playfair_cipher.playfair(text, alphabet, key, True, False)
decrypted_text = playfair_cipher.playfair(encrypted_text[0], alphabet, key, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_foursquare_cipher(self):
foursquare_cipher = ciphers.FourSquare()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key_1 = "KEYONE"
key_2 = "KEYTWO"
encrypted_text = foursquare_cipher.foursquare(text, alphabet, key_1, key_2, True, False)
decrypted_text = foursquare_cipher.foursquare(encrypted_text[0], alphabet, key_1, key_2, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_twosquare_cipher(self):
twosquare_cipher = ciphers.TwoSquare()
text = "Hello World"
alphabet = "abcdefghiklmnopqrstuvwxyz" # 25 chars, no j
key_1 = "KEYONE"
key_2 = "KEYTWO"
encrypted_text = twosquare_cipher.twosquare(text, alphabet, key_1, key_2, True, False)
decrypted_text = twosquare_cipher.twosquare(encrypted_text[0], alphabet, key_1, key_2, False, False)
# secretpy may add padding, so check for inclusion
assert text.lower().replace(" ", "") in decrypted_text[0]
def test_gronsfeld_cipher(self):
gronsfeld_cipher = ciphers.Gronsfeld()
text = "Hello World"
alphabet = "ENGLISH"
key = "1337"
encrypted_text = gronsfeld_cipher.gronsfeld(text, alphabet, key, True, False)
decrypted_text = gronsfeld_cipher.gronsfeld(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
def test_trifid_cipher(self):
trifid_cipher = ciphers.Trifid()
text = "HelloWorld"
# Trifid in secretpy uses a 27-char alphabet (letters + separator)
alphabet = "abcdefghijklmnopqrstuvwxyz."
key = 5 # period
encrypted_text = trifid_cipher.trifid(text, alphabet, key, True, False)
decrypted_text = trifid_cipher.trifid(encrypted_text[0], alphabet, key, False, False)
assert decrypted_text[0] == text.lower()
def test_zigzag_cipher(self):
zigzag_cipher = ciphers.Zigzag()
text = "Hello World"
key = 4 # rails
# The node wrapper for Zigzag doesn't use an alphabet, it's a pure transposition
encrypted_text = zigzag_cipher.zigzag(text, key, True, False)
decrypted_text = zigzag_cipher.zigzag(encrypted_text[0], key, False, False)
assert decrypted_text[0] == text.lower().replace(" ", "")
# Test suite for utils.py
class TestUtils:
# Converters
def test_string_to_binary(self):
string_to_binary = utils.String2Binary()
text = "Hello World"
encoding = "utf-8"
binary_text = string_to_binary.string2binary(text, encoding, "")
assert binary_text[0] == "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
def test_binary_to_string(self):
binary_to_string = utils.Binary2String()
binary_text = "1001000 1100101 1101100 1101100 1101111 100000 1010111 1101111 1110010 1101100 1100100"
encoding = "utf-8"
text = binary_to_string.binary2string(binary_text, encoding, "")
assert text[0] == "Hello World"
def test_string_to_hex(self):
string_to_hex = utils.String2Hex()
text = "Hello World"
encoding = "utf-8"
hex_text = string_to_hex.string2hex(text, encoding, "")
assert hex_text[0] == "48656c6c6f20576f726c64"
def test_hex_to_string(self):
hex_to_string = utils.Hex2String()
hex_text = "48656c6c6f20576f726c64"
encoding = "utf-8"
text = hex_to_string.hex2string(hex_text, encoding, "")
assert text[0] == "Hello World"
def test_string_to_base64(self):
string_to_base64 = utils.String2Base64()
text = "Hello World"
encoding = "utf-8"
base64_text = string_to_base64.string2base64(text, encoding, "")
assert base64_text[0] == "SGVsbG8gV29ybGQ="
def test_base64_to_string(self):
base64_to_string = utils.Base642String()
base64_text = "SGVsbG8gV29ybGQ="
encoding = "utf-8"
text = base64_to_string.base642string(base64_text, encoding, "")
assert text[0] == "Hello World"
# Bitwise Operators
def test_bitwise_and(self):
bitwise_and = utils.BitwiseAND()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_and.bitwiseand(text1, text2, encoding, "")
assert result[0] == "6065606c64"
def test_bitwise_or(self):
bitwise_or = utils.BitwiseOR()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_or.bitwiseor(text1, text2, encoding, "")
assert result[0] == "7f6f7e6c6f"
def test_bitwise_xor(self):
bitwise_xor = utils.BitwiseXOR()
text1 = "68656c6c6f"
text2 = "776f726c64"
encoding = "utf-8"
result = bitwise_xor.bitwisexor(text1, text2, encoding, "")
assert result[0] == "1f0a1e000b"
def test_bitwise_not(self):
bitwise_not = utils.BitwiseNOT()
text = "68656c6c6f"
encoding = "utf-8"
result = bitwise_not.bitwisenot(text, encoding, "")
assert result[0] == "979a939390"
# Test suite for auth_encrypt.py
class TestAuthEncrypt:
def test_chacha20poly1305(self):
chacha20poly1305 = auth_encrypt.ChaCha20Poly1305()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = chacha20poly1305.cc20(text, key, nonce, associated_data, True)
decrypted_text = chacha20poly1305.cc20(encrypted_text[0], key, nonce, associated_data, False)
assert decrypted_text[0] == text
def test_aes_gcm(self):
aes_gcm = auth_encrypt.AESAuth()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = aes_gcm.aesauth(text, key, nonce, associated_data, True, "AES-GCM", 16)
decrypted_text = aes_gcm.aesauth(encrypted_text[0], key, nonce, associated_data, False, "AES-GCM", 16)
assert decrypted_text[0] == text
def test_aes_ccm(self):
aes_ccm = auth_encrypt.AESAuth()
text = "Hello World"
key = "0" * 64
nonce = "0" * 24
associated_data = ""
encrypted_text = aes_ccm.aesauth(text, key, nonce, associated_data, True, "AES-CCM", 16)
decrypted_text = aes_ccm.aesauth(encrypted_text[0], key, nonce, associated_data, False, "AES-CCM", 16)
assert decrypted_text[0] == text
# Test suite for hashing.py
class TestHashing:
def test_sha256(self):
sha256 = hashing.SHA2()
text = "Hello World"
hashed_text = (sha256.sha2(key1=text, algorithm="SHA256"),)
assert hashed_text[0][0] == "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
def test_blake2b(self):
blake2b = hashing.BLAKE2()
text = "Hello World"
hashed_text = blake2b.blake2(key1=text, algorithm="BLAKE2b", digest_size=64)
assert (
hashed_text[0]
== "4386a08a265111c9896f56456e2cb61a64239115c4784cf438e36cc851221972da3fb0115f73cd02486254001f878ab1fd126aac69844ef1c1ca152379d0a9bd"
)
def test_sha3_256(self):
sha3_256 = hashing.SHA3()
text = "Hello World"
hashed_text = (sha3_256.sha3(key1=text, algorithm="SHA3_256"),)
assert hashed_text[0][0] == "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51"
def test_sha1(self):
sha1 = hashing.SHA1()
text = "Hello World"
hashed_text = (sha1.sha1(key1=text, algorithm=None),)
assert hashed_text[0][0] == "0a4d55a8d778e5022fab701977c5d840bbc486d0"
def test_md5(self):
md5 = hashing.MD5()
text = "Hello World"
hashed_text = (md5.md5(key1=text, algorithm=None),)
assert hashed_text[0][0] == "b10a8db164e0754105b7a99be72e3fe5"
def test_sm3(self):
sm3 = hashing.SM3()
text = "Hello World"
hashed_text = (sm3.sm3(key1=text, algorithm=None),)
assert hashed_text[0][0] == "77015816143ee627f4fa410b6dad2bdb9fcbdf1e061a452a686b8711a484c5d7"
def test_shake128(self):
shake128 = hashing.SHAKE()
text = "Hello World"
hashed_text = shake128.shake(
key1=text,
algorithm="SHAKE128",
output_length=32,
digest_size=64,
squeeze_bytes=16,
squeeze_times=2,
)
assert (
hashed_text[0][0]
== "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e2"
)
# Test suite for morse_code.py
class TestMorseCode:
def setup_method(self):
self.morse_code = morse_code.MorseCode()
def test_latin_morse_code(self):
text = "Hello World"
encoded_text = self.morse_code.MorseCode(text, True, "latin", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "latin", ".", "-")
assert decoded_text[0].lower() == text.lower()
def test_russian_morse_code(self):
text = "Привет мир"
encoded_text = self.morse_code.MorseCode(text, True, "russian", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "russian", ".", "-")
assert decoded_text[0].lower() == text.lower()
def test_arabic_morse_code(self):
text = "مرحبا بالعالم"
encoded_text = self.morse_code.MorseCode(text, True, "arabic", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "arabic", ".", "-")
assert decoded_text[0] == text
def test_hebrew_morse_code(self):
text = "שלום עולם"
encoded_text = self.morse_code.MorseCode(text, True, "hebrew", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "hebrew", ".", "-")
assert decoded_text[0] == "שלומ עולמ"
def test_greek_morse_code(self):
text = "Γειά σου Κόσμε"
encoded_text = self.morse_code.MorseCode(text, True, "greek", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "greek", ".", "-")
assert decoded_text[0] == "ΓΕΙΑ ΣΟΥ ΚΟΣΜΕ"
def test_korean_morse_code(self):
text = "안녕하세요"
encoded_text = self.morse_code.MorseCode(text, True, "korean", ".", "-")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "korean", ".", "-")
assert decoded_text[0] == "ㅇㅏㄴㄴㅕㅇㅎㅏㅅㅔㅇㅛ"
def test_japanese_wabun_morse_code(self):
text = "こんにちは"
normalized_text = unicodedata.normalize("NFKC", text)
print(f"Normalized text: {normalized_text}")
encoded_text = self.morse_code.MorseCode(text, True, "japanese-wabun", ".", "-")
print(f"Encoded text: {encoded_text}")
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "japanese-wabun", ".", "-")
print(f"Decoded text: {decoded_text}")
assert decoded_text == ("コンニチハ",)
def test_custom_dot_dash_morse_code(self):
text = "Hello World"
dot = "1"
dash = "0"
encoded_text = self.morse_code.MorseCode(text, True, "latin", dot, dash)
decoded_text = self.morse_code.MorseCode(encoded_text[0], False, "latin", dot, dash)
assert decoded_text[0].lower() == text.lower()
from src.comfyui_arg_toolkit.cryptography_primitives import const_time
from src.comfyui_arg_toolkit.cryptography_primitives import kdf
from src.comfyui_arg_toolkit.cryptography_primitives import key_wrapper
from src.comfyui_arg_toolkit.cryptography_primitives import symm_padding
from src.comfyui_arg_toolkit.cryptography_primitives import symmetrical_encrypt
class TestConstantTimeCompare:
def test_compare_equal(self):
compare = const_time.ConstantTimeCompare()
a = "deadbeef"
b = "deadbeef"
result = compare.compare(a, b)
assert result[0] is True
def test_compare_not_equal(self):
compare = const_time.ConstantTimeCompare()
a = "deadbeef"
b = "cafebabe"
result = compare.compare(a, b)
assert result[0] is False
class TestKeyDerivation:
def test_argon2id_derive_verify(self):
derive = kdf.Argon2id_Derive()
verify = kdf.Argon2id_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.argon2id_derive(message, 32, salt, 1, 4, 65536, "", "", True)
verified = verify.argon2id_verify(message, 32, salt, 1, 4, 65536, "", "", True, derived_key[0])
assert verified[0] is True
def test_pbkdf2hmac_derive_verify(self):
derive = kdf.PBKDF2HMAC_Derive()
verify = kdf.PBKDF2HMAC_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.pbkdf2hmac_derive(message, 32, salt, 1000, "SHA256")
verified = verify.pbkdf2hmac_verify(message, 32, salt, 1000, "SHA256", derived_key[0])
assert verified[0] is True
def test_scrypt_derive_verify(self):
derive = kdf.Scrypt_Derive()
verify = kdf.Scrypt_Verify()
message = "Hello World"
salt = "00" * 16
derived_key = derive.scrypt_derive(message, 32, salt, 14, 8, 1)
verified = verify.scrypt_verify(message, 32, salt, 14, 8, 1, derived_key[0])
assert verified[0] is True
class TestKeyWrapper:
def test_aeskeywrap(self):
wrapper = key_wrapper.AESKeyWrap()
wrapping_key = "00" * 32
key_to_wrap = "11" * 16
wrapped_key = wrapper.aeskeywrap(wrapping_key, key_to_wrap, True)
unwrapped_key = wrapper.aeskeywrap(wrapping_key, wrapped_key[0], False)
assert unwrapped_key[0] == key_to_wrap
def test_aeskeywrapwithpadding(self):
wrapper = key_wrapper.AESKeyWrapWithPadding()
wrapping_key = "00" * 32
key_to_wrap = "11" * 20 # Not a multiple of 8
wrapped_key = wrapper.aeskeywrapwithpadding(wrapping_key, key_to_wrap, True)
unwrapped_key = wrapper.aeskeywrapwithpadding(wrapping_key, wrapped_key[0], False)
assert unwrapped_key[0] == key_to_wrap
class TestSymmetricalPadding:
def test_pkcs7_padding(self):
padding_node = symm_padding.PaddingNode()
data = "Hello World"
padded_data = padding_node.padding(data, 128, "PKCS7", True)
unpadded_data = padding_node.padding(padded_data[0], 128, "PKCS7", False)
assert unpadded_data[0] == data
def test_ansix923_padding(self):
padding_node = symm_padding.PaddingNode()
data = "Hello World"
padded_data = padding_node.padding(data, 128, "ANSIX923", True)
unpadded_data = padding_node.padding(padded_data[0], 128, "ANSIX923", False)
assert unpadded_data[0] == data
class TestSymmetricalEncryption:
def test_aes_cbc_encryption_decryption(self):
enc_dec = symmetrical_encrypt.EncryptDecrypt()
text = "Hello World"
key = "00" * 32
iv = "11" * 16
# Pad the text first
padding_node = symm_padding.PaddingNode()
padded_text = padding_node.padding(text, 128, "PKCS7", True)
encrypted_text = enc_dec.encryptdecrypt(padded_text[0], key, iv, "", "AES", "CBC", True, 16, "")
decrypted_text_hex = enc_dec.encryptdecrypt(encrypted_text[0], key, iv, "", "AES", "CBC", False, 16, "")
print(f"Type: {type(decrypted_text_hex[0])}")
print(f"Value: {repr(decrypted_text_hex[0])}")
# Unpad the decrypted text
unpadded_data = padding_node.padding(decrypted_text_hex[0], 128, "PKCS7", False)
assert unpadded_data[0] == text