This commit is contained in:
parent
79b0491a75
commit
394143b4df
@ -260,7 +260,7 @@
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
<diagram id="4Sb7mgJDpsadGym-U4wz" name="Echanges">
|
||||
<mxGraphModel dx="1062" dy="587" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<mxGraphModel dx="1195" dy="683" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
@ -403,7 +403,7 @@
|
||||
<mxGeometry x="6.25" y="32.5" width="67.5" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pP7SjZfcCiBg3d1TCkzP-58" value="" style="html=1;shadow=0;dashed=0;align=center;verticalAlign=middle;shape=mxgraph.arrows2.arrow;dy=0;dx=10;notch=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="160" y="1160" width="360" height="230" as="geometry" />
|
||||
<mxGeometry x="160" y="1160" width="450" height="200" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pP7SjZfcCiBg3d1TCkzP-59" value="ENCRYPTED COMS" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=23;" parent="1" vertex="1">
|
||||
<mxGeometry x="305" y="1100" width="240" height="40" as="geometry" />
|
||||
@ -456,53 +456,55 @@
|
||||
<mxCell id="pP7SjZfcCiBg3d1TCkzP-77" value="=1096b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="327.5" y="970" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-1" value="Checksum" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="1280" width="65" height="80" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-1" value="CRC ?" style="swimlane;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" parent="1" vertex="1">
|
||||
<mxGeometry x="375" y="1270" width="63.25" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-2" value="CRC-32" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-1" vertex="1">
|
||||
<mxGeometry x="2.5" y="30" width="60" height="30" as="geometry" />
|
||||
<mxGeometry x="1.6199999999999992" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-3" value="Flag" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="1170" width="65" height="80" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-3" value="Flag" style="swimlane;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="1170" width="65" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-4" value=""IEM"" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-3" vertex="1">
|
||||
<mxGeometry x="2.5" y="30" width="60" height="30" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-4" value="To determine" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-3" vertex="1">
|
||||
<mxGeometry x="2.5" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-5" value="nbretry" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="253" y="1170" width="65" height="80" as="geometry" />
|
||||
<mxGeometry x="344.38" y="1170" width="65" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-6" value="0<span style="color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap-mode: nowrap;">%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22Flag%22%20style%3D%22swimlane%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22180%22%20y%3D%221090%22%20width%3D%2265%22%20height%3D%2280%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20value%3D%22%26quot%3BIEM%26quot%3B%22%20style%3D%22text%3Bhtml%3D1%3Balign%3Dcenter%3BverticalAlign%3Dmiddle%3BwhiteSpace%3Dwrap%3Brounded%3D0%3B%22%20vertex%3D%221%22%20parent%3D%222%22%3E%3CmxGeometry%20x%3D%222.5%22%20y%3D%2230%22%20width%3D%2260%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E</span>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-5" vertex="1">
|
||||
<mxGeometry x="2.5" y="30" width="60" height="30" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-6" value="y" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-5" vertex="1">
|
||||
<mxGeometry x="2.5" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-7" value="msg_len" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="325" y="1170" width="65" height="80" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-7" value="msg_len" style="swimlane;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" parent="1" vertex="1">
|
||||
<mxGeometry x="262.5" y="1170" width="65" height="60" as="geometry">
|
||||
<mxRectangle x="262.5" y="1170" width="90" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-8" value="XXX" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-7" vertex="1">
|
||||
<mxGeometry x="2.5" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-9" value="msg" style="swimlane;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;" parent="1" vertex="1">
|
||||
<mxGeometry x="187.5" y="1270" width="65" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-10" value="BBB" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-9" vertex="1">
|
||||
<mxGeometry x="2.5" y="30" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-9" value="msg" style="swimlane;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="423.75" y="1170" width="65" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-10" value="XXX" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="_H5URFloX_BVB2BL7kO6-9" vertex="1">
|
||||
<mxGeometry x="2.5" y="30" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-11" value="24b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="1250" width="60" height="30" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-11" value="16b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="180" y="1230" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-12" value="8b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="258" y="1250" width="55" height="30" as="geometry" />
|
||||
<mxGeometry x="349.38" y="1230" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-13" value="16b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="330" y="1250" width="55" height="30" as="geometry" />
|
||||
<mxGeometry x="267.5" y="1230" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-14" value="yyy" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="428.75" y="1250" width="55" height="30" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-14" value="96b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="510" y="1230" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-15" value="32b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="185" y="1360" width="55" height="30" as="geometry" />
|
||||
<mxGeometry x="379.12" y="1330" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-16" value="=80b + yyy" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="389.38" y="1330" width="100" height="30" as="geometry" />
|
||||
<mxCell id="_H5URFloX_BVB2BL7kO6-16" value="= (180b ~ 212b) + yyy" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="465" y="1285" width="130" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-2" value="Cypher" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="375" y="130" width="58.75" height="80" as="geometry" />
|
||||
@ -522,6 +524,42 @@
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-7" value="4b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="601.88" y="350" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-8" value="status" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="425" y="1170" width="65" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-9" value="CRC ?" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="pWkGvNQAXuiST1IiWYlx-8">
|
||||
<mxGeometry x="2.5" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-10" value="4b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="428.75" y="1230" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-11" value="iv" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="505" y="1170" width="65" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-12" value="random<div>(+Z)</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="pWkGvNQAXuiST1IiWYlx-11">
|
||||
<mxGeometry x="2.5" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-13" value="BBB b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="193" y="1330" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-14" value="MAC" style="swimlane;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
|
||||
<mxGeometry x="286.13" y="1270" width="63.25" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-15" value="AEAD" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="pWkGvNQAXuiST1IiWYlx-14">
|
||||
<mxGeometry x="1.6199999999999992" y="25" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-16" value="128b" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="290.25" y="1330" width="55" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-17" value="Green = clear data" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
|
||||
<mxGeometry x="10" y="1170" width="110" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-18" value="<font style="color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));">White = additional data</font>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fillColor=none;strokeColor=light-dark(#6C8EBF,#FFFFFF);" vertex="1" parent="1">
|
||||
<mxGeometry y="1220" width="130" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pWkGvNQAXuiST1IiWYlx-19" value="Blue = encrypted data" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;" vertex="1" parent="1">
|
||||
<mxGeometry x="10" y="1270" width="110" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
|
@ -14,7 +14,6 @@ def main():
|
||||
print(f"{YELLOW}\n======================================")
|
||||
print(" Icing Protocol - Manual CLI Demo ")
|
||||
print("======================================\n" + RESET)
|
||||
|
||||
print(f"Listening on port: {protocol.local_port}")
|
||||
print(f"Your identity public key (hex): {protocol.identity_pubkey.hex()}")
|
||||
print("\nAvailable commands:")
|
||||
@ -22,91 +21,90 @@ def main():
|
||||
print(" connect <port>")
|
||||
print(" generate_ephemeral_keys")
|
||||
print(" send_ping")
|
||||
print(" respond_ping <index> <0|1>")
|
||||
print(" send_handshake")
|
||||
print(" respond_ping <index> <0|1>")
|
||||
print(" generate_ecdhe <index>")
|
||||
print(" derive_hkdf")
|
||||
print(" send_encrypted <plaintext>")
|
||||
print(" decrypt_message <hex_message>")
|
||||
print(" auto_responder <on|off>")
|
||||
print(" show_state")
|
||||
print(" exit\n")
|
||||
|
||||
while True:
|
||||
while True:
|
||||
try:
|
||||
line = input("Cmd> ").strip()
|
||||
except EOFError:
|
||||
break
|
||||
if not line:
|
||||
try:
|
||||
line = input("Cmd> ").strip()
|
||||
except EOFError:
|
||||
break
|
||||
if not line:
|
||||
continue
|
||||
parts = line.split()
|
||||
cmd = parts[0].lower()
|
||||
if cmd == "exit":
|
||||
protocol.stop()
|
||||
break
|
||||
elif cmd == "show_state":
|
||||
protocol.show_state()
|
||||
elif cmd == "set_peer_identity":
|
||||
if len(parts) != 2:
|
||||
print("Usage: set_peer_identity <hex_pubkey>")
|
||||
continue
|
||||
parts = line.split()
|
||||
cmd = parts[0].lower()
|
||||
|
||||
if cmd == "exit":
|
||||
protocol.stop()
|
||||
sys.exit(0)
|
||||
|
||||
elif cmd == "show_state":
|
||||
protocol.show_state()
|
||||
|
||||
elif cmd == "set_peer_identity":
|
||||
if len(parts) != 2:
|
||||
print("Usage: set_peer_identity <hex_pubkey>")
|
||||
continue
|
||||
protocol.set_peer_identity(parts[1])
|
||||
|
||||
elif cmd == "connect":
|
||||
if len(parts) != 2:
|
||||
print("Usage: connect <port>")
|
||||
continue
|
||||
try:
|
||||
port = int(parts[1])
|
||||
protocol.connect_to_peer(port)
|
||||
except ValueError:
|
||||
print("Invalid port.")
|
||||
|
||||
elif cmd == "generate_ephemeral_keys":
|
||||
protocol.generate_ephemeral_keys()
|
||||
|
||||
elif cmd == "send_ping":
|
||||
protocol.send_ping_request()
|
||||
|
||||
elif cmd == "send_handshake":
|
||||
protocol.send_handshake()
|
||||
|
||||
elif cmd == "respond_ping":
|
||||
if len(parts) != 3:
|
||||
print("Usage: respond_ping <index> <0|1>")
|
||||
continue
|
||||
try:
|
||||
idx = int(parts[1])
|
||||
ac = int(parts[2])
|
||||
protocol.respond_to_ping(idx, ac)
|
||||
except ValueError:
|
||||
print("Index and answer must be integers.")
|
||||
|
||||
elif cmd == "generate_ecdhe":
|
||||
if len(parts) != 2:
|
||||
print("Usage: generate_ecdhe <index>")
|
||||
continue
|
||||
try:
|
||||
idx = int(parts[1])
|
||||
protocol.generate_ecdhe(idx)
|
||||
except ValueError:
|
||||
print("Index must be an integer.")
|
||||
|
||||
elif cmd == "derive_hkdf":
|
||||
protocol.derive_hkdf()
|
||||
|
||||
elif cmd == "auto_responder":
|
||||
if len(parts) != 2:
|
||||
print("Usage: auto_responder <on|off>")
|
||||
continue
|
||||
arg = parts[1].lower()
|
||||
protocol.enable_auto_responder(arg == "on")
|
||||
|
||||
else:
|
||||
print(f"{RED}[ERROR]{RESET} Unknown command: {cmd}")
|
||||
|
||||
protocol.set_peer_identity(parts[1])
|
||||
elif cmd == "connect":
|
||||
if len(parts) != 2:
|
||||
print("Usage: connect <port>")
|
||||
continue
|
||||
try:
|
||||
port = int(parts[1])
|
||||
protocol.connect_to_peer(port)
|
||||
except ValueError:
|
||||
print("Invalid port.")
|
||||
elif cmd == "generate_ephemeral_keys":
|
||||
protocol.generate_ephemeral_keys()
|
||||
elif cmd == "send_ping":
|
||||
protocol.send_ping_request()
|
||||
elif cmd == "send_handshake":
|
||||
protocol.send_handshake()
|
||||
elif cmd == "respond_ping":
|
||||
if len(parts) != 3:
|
||||
print("Usage: respond_ping <index> <0|1>")
|
||||
continue
|
||||
try:
|
||||
idx = int(parts[1])
|
||||
ac = int(parts[2])
|
||||
protocol.respond_to_ping(idx, ac)
|
||||
except ValueError:
|
||||
print("Index and answer must be integers.")
|
||||
elif cmd == "generate_ecdhe":
|
||||
if len(parts) != 2:
|
||||
print("Usage: generate_ecdhe <index>")
|
||||
continue
|
||||
try:
|
||||
idx = int(parts[1])
|
||||
protocol.generate_ecdhe(idx)
|
||||
except ValueError:
|
||||
print("Index must be an integer.")
|
||||
elif cmd == "derive_hkdf":
|
||||
protocol.derive_hkdf()
|
||||
elif cmd == "send_encrypted":
|
||||
if len(parts) < 2:
|
||||
print("Usage: send_encrypted <plaintext>")
|
||||
continue
|
||||
# Join the rest of the line as plaintext
|
||||
plaintext = " ".join(parts[1:])
|
||||
protocol.send_encrypted_message(plaintext)
|
||||
elif cmd == "decrypt_message":
|
||||
if len(parts) != 2:
|
||||
print("Usage: decrypt_message <hex_message>")
|
||||
continue
|
||||
protocol.decrypt_encrypted_message(parts[1])
|
||||
elif cmd == "auto_responder":
|
||||
if len(parts) != 2:
|
||||
print("Usage: auto_responder <on|off>")
|
||||
continue
|
||||
protocol.enable_auto_responder(parts[1].lower() == "on")
|
||||
else:
|
||||
print(f"{RED}[ERROR]{RESET} Unknown command: {cmd}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
94
protocol_prototype/encryption.py
Normal file
94
protocol_prototype/encryption.py
Normal file
@ -0,0 +1,94 @@
|
||||
import os
|
||||
import struct
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
|
||||
class MessageHeader:
|
||||
"""
|
||||
Represents the header of an encrypted message.
|
||||
- flag (16 bits)
|
||||
- data_len (16 bits): length in bytes of the encrypted payload (excluding tag)
|
||||
- Associated Data (AD):
|
||||
* retry (8 bits)
|
||||
* connexion_status (4 bits) + 4 bits padding (packed in one byte)
|
||||
* iv/messageID (96 bits / 12 bytes)
|
||||
Total header size: 2 + 2 + 1 + 1 + 12 = 18 bytes.
|
||||
"""
|
||||
def __init__(self, flag: int, data_len: int, retry: int, connexion_status: int, iv: bytes):
|
||||
self.flag = flag # 16 bits
|
||||
self.data_len = data_len # 16 bits
|
||||
self.retry = retry # 8 bits
|
||||
self.connexion_status = connexion_status # 4 bits
|
||||
self.iv = iv # 96 bits (12 bytes)
|
||||
|
||||
def pack(self) -> bytes:
|
||||
# Pack flag and data_len as unsigned shorts (2 bytes each)
|
||||
header = struct.pack('>H H', self.flag, self.data_len)
|
||||
# Pack retry (1 byte) and connexion_status (4 bits in high nibble, 4 bits padding as zero)
|
||||
ad_byte = (self.connexion_status & 0x0F) << 4
|
||||
ad_packed = struct.pack('>B B', self.retry, ad_byte)
|
||||
# Append IV (12 bytes)
|
||||
return header + ad_packed + self.iv
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, data: bytes) -> 'MessageHeader':
|
||||
# Expect exactly 18 bytes
|
||||
flag, data_len = struct.unpack('>H H', data[:4])
|
||||
retry, ad_byte = struct.unpack('>B B', data[4:6])
|
||||
connexion_status = (ad_byte >> 4) & 0x0F
|
||||
iv = data[6:18]
|
||||
return cls(flag, data_len, retry, connexion_status, iv)
|
||||
|
||||
def generate_iv(initial: bool, previous_iv: bytes = None) -> bytes:
|
||||
"""
|
||||
Generate a 96-bit IV (12 bytes).
|
||||
- If 'initial' is True, return a random IV.
|
||||
- Otherwise, increment the previous IV by 1 modulo 2^96.
|
||||
"""
|
||||
if initial or previous_iv is None:
|
||||
return os.urandom(12)
|
||||
else:
|
||||
iv_int = int.from_bytes(previous_iv, 'big')
|
||||
iv_int = (iv_int + 1) % (1 << 96)
|
||||
return iv_int.to_bytes(12, 'big')
|
||||
|
||||
def encrypt_message(plaintext: bytes, key: bytes, flag: int = 0xBEEF, retry: int = 0, connexion_status: int = 0) -> bytes:
|
||||
"""
|
||||
Encrypts a plaintext using AES-256-GCM.
|
||||
- Generates a random 96-bit IV.
|
||||
- Encrypts the plaintext with AESGCM.
|
||||
- Builds a MessageHeader with the provided flag, the data_len (length of ciphertext excluding tag),
|
||||
retry, connexion_status, and the IV.
|
||||
- Returns the full encrypted message: header (18 bytes) || ciphertext || tag (16 bytes).
|
||||
"""
|
||||
aesgcm = AESGCM(key)
|
||||
iv = generate_iv(initial=True)
|
||||
# Encrypt with no associated data (you may later use the header as AD if needed)
|
||||
ciphertext_with_tag = aesgcm.encrypt(iv, plaintext, None)
|
||||
tag_length = 16 # default tag size
|
||||
ciphertext = ciphertext_with_tag[:-tag_length]
|
||||
tag = ciphertext_with_tag[-tag_length:]
|
||||
data_len = len(ciphertext)
|
||||
header = MessageHeader(flag=flag, data_len=data_len, retry=retry, connexion_status=connexion_status, iv=iv)
|
||||
packed_header = header.pack()
|
||||
return packed_header + ciphertext + tag
|
||||
|
||||
def decrypt_message(message: bytes, key: bytes) -> bytes:
|
||||
"""
|
||||
Decrypts a message that was encrypted with encrypt_message.
|
||||
Expects message format: header (18 bytes) || ciphertext || tag (16 bytes).
|
||||
Returns the decrypted plaintext.
|
||||
"""
|
||||
if len(message) < 18 + 16:
|
||||
raise ValueError("Message too short.")
|
||||
header_bytes = message[:18]
|
||||
header = MessageHeader.unpack(header_bytes)
|
||||
data_len = header.data_len
|
||||
expected_len = 18 + data_len + 16
|
||||
if len(message) != expected_len:
|
||||
raise ValueError("Message length does not match header's data_len.")
|
||||
ciphertext = message[18:18+data_len]
|
||||
tag = message[18+data_len:]
|
||||
ciphertext_with_tag = ciphertext + tag
|
||||
aesgcm = AESGCM(key)
|
||||
plaintext = aesgcm.decrypt(header.iv, ciphertext_with_tag, None)
|
||||
return plaintext
|
@ -20,8 +20,7 @@ from messages import (
|
||||
)
|
||||
import transmission
|
||||
|
||||
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from encryption import encrypt_message, decrypt_message
|
||||
|
||||
# ANSI colors
|
||||
RED = "\033[91m"
|
||||
@ -468,3 +467,46 @@ class IcingProtocol:
|
||||
self.connections.clear()
|
||||
self.inbound_messages.clear()
|
||||
print(f"{RED}[STOP]{RESET} Protocol stopped.")
|
||||
|
||||
# New method: Send an encrypted message over the first active connection.
|
||||
def send_encrypted_message(self, plaintext: str):
|
||||
"""
|
||||
Encrypts the provided plaintext (a UTF-8 string) using the derived HKDF key (AES-256),
|
||||
and sends the encrypted message over the first active connection.
|
||||
The message format is: header (18 bytes) || ciphertext || tag (16 bytes).
|
||||
"""
|
||||
if not self.connections:
|
||||
print(f"{RED}[ERROR]{RESET} No active connections.")
|
||||
return
|
||||
if not self.hkdf_key:
|
||||
print(f"{RED}[ERROR]{RESET} No HKDF key derived. Cannot encrypt message.")
|
||||
return
|
||||
key = bytes.fromhex(self.hkdf_key)
|
||||
plaintext_bytes = plaintext.encode('utf-8')
|
||||
encrypted = encrypt_message(plaintext_bytes, key)
|
||||
# Send the encrypted message over the first connection.
|
||||
self._send_packet(self.connections[0], encrypted, "ENCRYPTED_MESSAGE")
|
||||
print(f"{GREEN}[SEND_ENCRYPTED]{RESET} Encrypted message sent.")
|
||||
|
||||
# New method: Decrypt an encrypted message provided as a hex string.
|
||||
def decrypt_encrypted_message(self, hex_message: str):
|
||||
"""
|
||||
Decrypts an encrypted message (given as a hex string) using the HKDF key.
|
||||
Returns the plaintext (UTF-8 string) and prints it.
|
||||
"""
|
||||
if not self.hkdf_key:
|
||||
print(f"{RED}[ERROR]{RESET} No HKDF key derived. Cannot decrypt message.")
|
||||
return
|
||||
try:
|
||||
message_bytes = bytes.fromhex(hex_message)
|
||||
except Exception as e:
|
||||
print(f"{RED}[ERROR]{RESET} Invalid hex input.")
|
||||
return
|
||||
key = bytes.fromhex(self.hkdf_key)
|
||||
try:
|
||||
plaintext_bytes = decrypt_message(message_bytes, key)
|
||||
plaintext = plaintext_bytes.decode('utf-8')
|
||||
print(f"{GREEN}[DECRYPTED]{RESET} Decrypted message: {plaintext}")
|
||||
return plaintext
|
||||
except Exception as e:
|
||||
print(f"{RED}[ERROR]{RESET} Decryption failed: {e}")
|
||||
|
Loading…
Reference in New Issue
Block a user