A bheith ina forbrĂłir
Spreag sĂ© seo go lĂ©ir mĂ© an t-alt seo a scrĂobh chun a thaispeĂĄint nach tasc chomh deacair Ă© prĂłtacail cripteagrafacha agus IM slĂĄn a chur i bhfeidhm. Mar sin fĂ©in, nĂ fiĂș do phrĂłtacail fĂordheimhnithe agus eochair-chomhaontaithe fĂ©in a chumadh.
Beidh an t-alt ag scrĂobh
Dearadh IM
Ar dtĂșs, nĂ mĂłr dĂșinn a thuiscint cad a bheidh ar ĂĄr n-GS cosĂșil. Ar mhaithe le simplĂocht, bĂodh gur grĂ©asĂĄn piara le piaraĂ Ă©, gan teacht ar rannphĂĄirtithe ar bith. Cuirfimid in iĂșl go pearsanta cĂ©n seoladh: calafort le nascadh leis chun cumarsĂĄid a dhĂ©anamh leis an idirghabhĂĄlaĂ.
Tuigim, ag an am seo, gur teorannĂș suntasach Ă© an toimhde go bhfuil cumarsĂĄid dhĂreach ar fĂĄil idir dhĂĄ rĂomhaire treallach ar infheidhmeacht GS i gcleachtas. Ach dĂĄ mhĂ©ad forbrĂłirĂ a chuireann gach cineĂĄl crutches trasnaithe NAT i bhfeidhm, is amhlaidh is faide a fhanfaimid ar an IdirlĂon IPv4, agus is dĂłcha go mbeidh cumarsĂĄid idir rĂomhairĂ treallach ann. CĂ© chomh fada is fĂ©idir leat an easpa IPv6 a fhulaingt sa bhaile agus ag an obair?
Beidh lĂonra cairde le cara againn: nĂ mĂłr fios a bheith ag gach idirghabhĂĄlaĂ fĂ©ideartha roimh rĂ©. Ar an gcĂ©ad dul sĂos, dĂ©anann sĂ© seo gach rud a shimpliĂș go mĂłr: thugamar isteach muid fĂ©in, fuaireamar nĂł nĂor aimsigh an t-ainm/eochair, dĂnasctha nĂł lean ar aghaidh ag obair, agus an t-idirghabhĂĄlaĂ ar an eolas. Ar an dara dul sĂos, go ginearĂĄlta, tĂĄ sĂ© slĂĄn agus cuireann sĂ© deireadh le go leor ionsaithe.
Beidh an comhéadan IM gar do réitigh clasaiceacha
- iâDĂ©antar teachtaireachtaĂ a sheoltar chuig an idirghabhĂĄlaĂ a thaifeadadh ann;
- amach - léitear teachtaireachtaà a fhaightear ón idirghabhålaà uaidh;
- luaigh - trà léamh uaidh, faighimid amach an bhfuil an t-idirghabhålaà ceangailte faoi låthair, an seoladh ceangail/port.
Ina theannta sin, cruthaĂtear soicĂ©ad conn, trĂd an gcalafort Ăłstach a scrĂobh isteach ina gcuirimid tĂșs le nasc leis an gcian-idirghabhĂĄlaĂ.
|-- alice
| |-- in
| |-- out
| `-- state
|-- bob
| |-- in
| |-- out
| `-- state
`- conn
Ligeann an cur chuige seo duit feidhmiĂș neamhspleĂĄch a dhĂ©anamh ar iompar GS agus comhĂ©adan ĂșsĂĄideora, toisc nach bhfuil aon chara ann, nĂ fĂ©idir leat gach duine a shĂĄsamh. Ag baint ĂșsĂĄide as
Go deimhin, ĂșsĂĄideann tionscadail suckless comhaid FIFO. Go pearsanta, nĂ raibh mĂ© in ann a thuiscint conas a bheith ag obair le comhaid iomaĂoch in asyncio gan cĂșlra lĂĄmhscrĂofa Ăł snĂĄitheanna tiomnaithe (TĂĄ mĂ© ag baint ĂșsĂĄide as an teanga le haghaidh a leithĂ©id de rudaĂ le fada an lĂĄ
An prĂłtacal neamhdhaingean bunaidh
ĂsĂĄidtear TCP mar iompar: rĂĄthaĂonn sĂ© seachadadh agus a ordĂș. NĂ rĂĄthaĂonn UDP ceachtar acu (rud a bheadh ââĂșsĂĄideach nuair a ĂșsĂĄidtear cripteagrafaĂocht), ach tacaĂocht
Ar an drochuair, i TCP nĂl aon choincheap de theachtaireacht, ach sruth beart. Mar sin, is gĂĄ teacht suas le formĂĄid do theachtaireachtaĂ ionas gur fĂ©idir iad a roinnt eatarthu fĂ©in sa snĂĄithe seo. Is fĂ©idir linn aontĂș an carachtar beatha lĂne a ĂșsĂĄid. TĂĄ sĂ© ceart go leor do thosaitheoirĂ, ach a luaithe a thosaĂmid ag criptiĂș ĂĄr dteachtaireachtaĂ, fĂ©adfaidh an carachtar seo a bheith le feiceĂĄil ĂĄit ar bith sa ciphertext. I lĂonraĂ, mar sin, is iad na prĂłtacail mhĂłrĂ©ilimh iad siĂșd a sheolann fad na teachtaireachta i mbearta den chĂ©ad uair. Mar shampla, as an mbosca tĂĄ xdrlib ag Python, a ligeann duit oibriĂș le formĂĄid den chineĂĄl cĂ©anna
NĂ oibreoimid i gceart agus go hĂ©ifeachtach le lĂ©amh TCP - dĂ©anfaimid an cĂłd a shimpliĂș. LĂ©imid sonraĂ Ăłn soicĂ©ad i lĂșb gan teorainn go dtĂ go ndĂ©anaimid an teachtaireacht iomlĂĄn a dhĂchĂłdĂș. Is fĂ©idir JSON le XML a ĂșsĂĄid mar fhormĂĄid don chur chuige seo freisin. Ach nuair a chuirtear cripteagrafaĂocht leis, nĂ mĂłr na sonraĂ a shĂniĂș agus a fhĂordheimhniĂș - agus beidh gĂĄ le lĂ©iriĂș comhionann beart-ar-beart ar oibiachtaĂ, rud nach solĂĄthraĂonn JSON/XML (dâfhĂ©adfadh go mbeadh Ă©agsĂșlacht ag baint le torthaĂ dumpaĂ).
TĂĄ XDR oiriĂșnach don tasc seo, ach roghnaĂonn mĂ© ASN.1 le ionchĂłdĂș DER agus
# Msg ::= CHOICE {
# text MsgText,
# handshake [0] EXPLICIT MsgHandshake }
class Msg(Choice):
schema = ((
("text", MsgText()),
("handshake", MsgHandshake(expl=tag_ctxc(0))),
))
# MsgText ::= SEQUENCE {
# text UTF8String (SIZE(1..MaxTextLen))}
class MsgText(Sequence):
schema = ((
("text", UTF8String(bounds=(1, MaxTextLen))),
))
# MsgHandshake ::= SEQUENCE {
# peerName UTF8String (SIZE(1..256)) }
class MsgHandshake(Sequence):
schema = ((
("peerName", UTF8String(bounds=(1, 256))),
))
Msg a bheidh sa teachtaireacht a gheofar: tĂ©acs MsgText (le rĂ©imse tĂ©acs amhĂĄin faoi lĂĄthair) nĂł teachtaireacht chroitheadh ââlĂĄimhe MsgHandshake (ina bhfuil ainm an idirghabhĂĄlaĂ). Anois tĂĄ cuma rĂł-chasta air, ach is bunĂșs Ă© seo don todhchaĂ.
âââââââ âââââââ â PeerAâ âPeerBâ ââââŹâââââââ âââââââ ) â âââââââââ â ââââââââ>â â â â â Croitheadh ââLĂĄimhe(IdB) â â<ââââââââââââââ â MsgText() â ââââ â MsgText() â â â
IM gan cripteagrafaĂocht
Mar a dĂșirt mĂ© cheana, ĂșsĂĄidfear an leabharlann asyncio do gach oibrĂocht soicĂ©ad. DĂ©anaimis a bhfuil sĂșil againn a fhĂłgairt ag an seoladh:
parser = argparse.ArgumentParser(description="GOSTIM")
parser.add_argument(
"--our-name",
required=True,
help="Our peer name",
)
parser.add_argument(
"--their-names",
required=True,
help="Their peer names, comma-separated",
)
parser.add_argument(
"--bind",
default="::1",
help="Address to listen on",
)
parser.add_argument(
"--port",
type=int,
default=6666,
help="Port to listen on",
)
args = parser.parse_args()
OUR_NAME = UTF8String(args.our_name)
THEIR_NAMES = set(args.their_names.split(","))
Socraigh d'ainm fĂ©in (--ĂĄr n-ainm alice). TĂĄ na hidirghabhĂĄlaithe go lĂ©ir a bhfuiltear ag sĂșil leo liostaithe scartha le camĂłga ( âa n-ainmneacha bob, oĂche). I gcĂĄs gach ceann de na hidirghabhĂĄlaithe, cruthaĂtear eolaire le soicĂ©id Unix, chomh maith le coroutine do gach duine isteach, amach, luaigh:
for peer_name in THEIR_NAMES:
makedirs(peer_name, mode=0o700, exist_ok=True)
out_queue = asyncio.Queue()
OUT_QUEUES[peer_name] = out_queue
asyncio.ensure_future(asyncio.start_unix_server(
partial(unixsock_out_processor, out_queue=out_queue),
path.join(peer_name, "out"),
))
in_queue = asyncio.Queue()
IN_QUEUES[peer_name] = in_queue
asyncio.ensure_future(asyncio.start_unix_server(
partial(unixsock_in_processor, in_queue=in_queue),
path.join(peer_name, "in"),
))
asyncio.ensure_future(asyncio.start_unix_server(
partial(unixsock_state_processor, peer_name=peer_name),
path.join(peer_name, "state"),
))
asyncio.ensure_future(asyncio.start_unix_server(unixsock_conn_processor, "conn"))
Seoltar teachtaireachtaĂ a thagann Ăłn ĂșsĂĄideoir Ăłn soicĂ©ad isteach chuig an scuaine IN_QUEUES:
async def unixsock_in_processor(reader, writer, in_queue: asyncio.Queue) -> None:
while True:
text = await reader.read(MaxTextLen)
if text == b"":
break
await in_queue.put(text.decode("utf-8"))
Seoltar teachtaireachtaĂ a thagann Ăł idirghabhĂĄlaithe chuig scuainĂ OUT_QUEUES, Ăłna scrĂobhtar sonraĂ chuig an soicĂ©ad amach:
async def unixsock_out_processor(reader, writer, out_queue: asyncio.Queue) -> None:
while True:
text = await out_queue.get()
writer.write(("[%s] %s" % (datetime.now(), text)).encode("utf-8"))
await writer.drain()
Agus tĂș ag lĂ©amh Ăł shoicĂ©ad stĂĄit, lorgaĂonn an clĂĄr seoladh an idirghabhĂĄlaĂ san fhoclĂłir PEER_ALIVE. Mura bhfuil aon nasc leis an idirghabhĂĄlaĂ fĂłs, scrĂobhtar lĂne fholamh.
async def unixsock_state_processor(reader, writer, peer_name: str) -> None:
peer_writer = PEER_ALIVES.get(peer_name)
writer.write(
b"" if peer_writer is None else (" ".join([
str(i) for i in peer_writer.get_extra_info("peername")[:2]
]).encode("utf-8") + b"n")
)
await writer.drain()
writer.close()
Agus seoladh ĂĄ scrĂobh chuig soicĂ©ad conn, seoltar an fheidhm âtionscnĂłirâ naisc:
async def unixsock_conn_processor(reader, writer) -> None:
data = await reader.read(256)
writer.close()
host, port = data.decode("utf-8").split(" ")
await initiator(host=host, port=int(port))
DĂ©anaimis machnamh ar an tionscnĂłir. Ar dtĂșs is lĂ©ir go n-osclaĂonn sĂ© nasc leis an Ăłsta/port sonraithe agus seolann sĂ© teachtaireacht chroitheadh ââlĂĄimhe darb ainm:
130 async def initiator(host, port):
131 _id = repr((host, port))
132 logging.info("%s: dialing", _id)
133 reader, writer = await asyncio.open_connection(host, port)
134 # Handshake message {{{
135 writer.write(Msg(("handshake", MsgHandshake((
136 ("peerName", OUR_NAME),
137 )))).encode())
138 # }}}
139 await writer.drain()
Ansin, fanann sĂ© ar fhreagra Ăłn gcĂłisir iargĂșlta. DĂ©anann sĂ© iarracht an freagra isteach a dhĂchĂłdĂș trĂ ĂșsĂĄid a bhaint as scĂ©im Msg ASN.1. Glacaimid leis go seolfar an teachtaireacht ar fad i mĂr TCP amhĂĄin agus go bhfaighfimid go adamhach Ă© nuair a ghlaoimid ar .read(). DĂ©anaimid seiceĂĄil go bhfuaireamar an teachtaireacht chroitheadh ââlĂĄimhe.
141 # Wait for Handshake message {{{
142 data = await reader.read(256)
143 if data == b"":
144 logging.warning("%s: no answer, disconnecting", _id)
145 writer.close()
146 return
147 try:
148 msg, _ = Msg().decode(data)
149 except ASN1Error:
150 logging.warning("%s: undecodable answer, disconnecting", _id)
151 writer.close()
152 return
153 logging.info("%s: got %s message", _id, msg.choice)
154 if msg.choice != "handshake":
155 logging.warning("%s: unexpected message, disconnecting", _id)
156 writer.close()
157 return
158 # }}}
DĂ©anaimid seiceĂĄil go bhfuil ainm faighte an idirghabhĂĄlaĂ ar eolas againn. Mura bhfuil, ansin briseann muid an nasc. DĂ©anaimid seiceĂĄil an bhfuil nasc bunaithe againn cheana fĂ©in leis (thug an t-idirghabhĂĄlaĂ an t-ordĂș arĂs chun ceangal a dhĂ©anamh linn) agus Ă© a dhĂșnadh. CoinnĂonn an scuaine IN_QUEUES teaghrĂĄin Python le tĂ©acs na teachtaireachta, ach tĂĄ luach ar leith ag None a thugann comhartha don choroutine msg_sender stop a bheith ag obair ionas go ndĂ©anann sĂ© dearmad ar a scrĂbhneoir a bhaineann leis an nasc oidhreachta TCP.
159 msg_handshake = msg.value
160 peer_name = str(msg_handshake["peerName"])
161 if peer_name not in THEIR_NAMES:
162 logging.warning("unknown peer name: %s", peer_name)
163 writer.close()
164 return
165 logging.info("%s: session established: %s", _id, peer_name)
166 # Run text message sender, initialize transport decoder {{{
167 peer_alive = PEER_ALIVES.pop(peer_name, None)
168 if peer_alive is not None:
169 peer_alive.close()
170 await IN_QUEUES[peer_name].put(None)
171 PEER_ALIVES[peer_name] = writer
172 asyncio.ensure_future(msg_sender(peer_name, writer))
173 # }}}
glacann msg_sender le teachtaireachtaĂ amach (ciĂșĂĄilte Ăł shoicĂ©ad isteach), cuireann sĂ© iad i dteachtaireacht MsgText agus seolann sĂ© thar nasc TCP iad. Is fĂ©idir Ă© a bhriseadh trĂĄth ar bith - tĂĄimid idircheapadh go soilĂ©ir seo.
async def msg_sender(peer_name: str, writer) -> None:
in_queue = IN_QUEUES[peer_name]
while True:
text = await in_queue.get()
if text is None:
break
writer.write(Msg(("text", MsgText((
("text", UTF8String(text)),
)))).encode())
try:
await writer.drain()
except ConnectionResetError:
del PEER_ALIVES[peer_name]
return
logging.info("%s: sent %d characters message", peer_name, len(text))
Ag an deireadh, cuireann an tionscnĂłir lĂșb gan teorainn de teachtaireachtaĂ lĂ©itheoireachta Ăłn soicĂ©ad. SeiceĂĄlann cibĂ© acu an teachtaireachtaĂ tĂ©acs iad na teachtaireachtaĂ seo agus cuireann sĂ© sa scuaine OUT_QUEUES iad, Ăłna seolfar chuig soicĂ©ad amach an idirghabhĂĄlaĂ chomhfhreagraigh iad. CĂ©n fĂĄth nach fĂ©idir leat ach .read() a dhĂ©anamh agus an teachtaireacht a dhĂchĂłdĂș? Toisc gur fĂ©idir go ndĂ©anfar roinnt teachtaireachtaĂ Ăłn ĂșsĂĄideoir a chomhiomlĂĄnĂș i maolĂĄn an chĂłrais oibriĂșchĂĄin agus iad a sheoladh in aon mhĂr TCP amhĂĄin. Is fĂ©idir linn an chĂ©ad cheann a dhĂchĂłdĂș, agus ansin fĂ©adfaidh cuid den cheann ina dhiaidh sin fanacht sa mhaolĂĄn. I gcĂĄs aon chor neamhghnĂĄch, dĂșnaimid an nasc TCP agus stopaimid an coroutine msg_sender (trĂ None a sheoladh chuig an scuaine OUT_QUEUES).
174 buf = b""
175 # Wait for test messages {{{
176 while True:
177 data = await reader.read(MaxMsgLen)
178 if data == b"":
179 break
180 buf += data
181 if len(buf) > MaxMsgLen:
182 logging.warning("%s: max buffer size exceeded", _id)
183 break
184 try:
185 msg, tail = Msg().decode(buf)
186 except ASN1Error:
187 continue
188 buf = tail
189 if msg.choice != "text":
190 logging.warning("%s: unexpected %s message", _id, msg.choice)
191 break
192 try:
193 await msg_receiver(msg.value, peer_name)
194 except ValueError as err:
195 logging.warning("%s: %s", err)
196 break
197 # }}}
198 logging.info("%s: disconnecting: %s", _id, peer_name)
199 IN_QUEUES[peer_name].put(None)
200 writer.close()
66 async def msg_receiver(msg_text: MsgText, peer_name: str) -> None:
67 text = str(msg_text["text"])
68 logging.info("%s: received %d characters message", peer_name, len(text))
69 await OUT_QUEUES[peer_name].put(text)
Fillfimid ar an bprĂomhchĂłd. Tar Ă©is na coroutines go lĂ©ir a chruthĂș ag an am a thosaĂonn an clĂĄr, cuirimid tĂșs leis an bhfreastalaĂ TCP. I gcĂĄs gach nasc bunaithe, cruthaĂonn sĂ© coroutine freagrĂłra.
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s %(asctime)s: %(funcName)s: %(message)s",
)
loop = asyncio.get_event_loop()
server = loop.run_until_complete(asyncio.start_server(responder, args.bind, args.port))
logging.info("Listening on: %s", server.sockets[0].getsockname())
loop.run_forever()
TĂĄ an freagrĂłir cosĂșil leis an tionscnĂłir agus lĂ©irĂonn sĂ© na gnĂomhartha cĂ©anna go lĂ©ir, ach tosaĂonn lĂșb gan teorainn na dteachtaireachtaĂ lĂ©itheoireachta lĂĄithreach, ar mhaithe le simplĂocht. Faoi lĂĄthair, cuireann an prĂłtacal croitheadh ââlĂĄimhe teachtaireacht amhĂĄin Ăł gach taobh, ach sa todhchaĂ beidh dhĂĄ cheann Ăłn tionscnĂłir nasc, agus ina dhiaidh sin is fĂ©idir teachtaireachtaĂ tĂ©acs a sheoladh lĂĄithreach.
72 async def responder(reader, writer):
73 _id = writer.get_extra_info("peername")
74 logging.info("%s: connected", _id)
75 buf = b""
76 msg_expected = "handshake"
77 peer_name = None
78 while True:
79 # Read until we get Msg message {{{
80 data = await reader.read(MaxMsgLen)
81 if data == b"":
82 logging.info("%s: closed connection", _id)
83 break
84 buf += data
85 if len(buf) > MaxMsgLen:
86 logging.warning("%s: max buffer size exceeded", _id)
87 break
88 try:
89 msg, tail = Msg().decode(buf)
90 except ASN1Error:
91 continue
92 buf = tail
93 # }}}
94 if msg.choice != msg_expected:
95 logging.warning("%s: unexpected %s message", _id, msg.choice)
96 break
97 if msg_expected == "text":
98 try:
99 await msg_receiver(msg.value, peer_name)
100 except ValueError as err:
101 logging.warning("%s: %s", err)
102 break
103 # Process Handshake message {{{
104 elif msg_expected == "handshake":
105 logging.info("%s: got %s message", _id, msg_expected)
106 msg_handshake = msg.value
107 peer_name = str(msg_handshake["peerName"])
108 if peer_name not in THEIR_NAMES:
109 logging.warning("unknown peer name: %s", peer_name)
110 break
111 writer.write(Msg(("handshake", MsgHandshake((
112 ("peerName", OUR_NAME),
113 )))).encode())
114 await writer.drain()
115 logging.info("%s: session established: %s", _id, peer_name)
116 peer_alive = PEER_ALIVES.pop(peer_name, None)
117 if peer_alive is not None:
118 peer_alive.close()
119 await IN_QUEUES[peer_name].put(None)
120 PEER_ALIVES[peer_name] = writer
121 asyncio.ensure_future(msg_sender(peer_name, writer))
122 msg_expected = "text"
123 # }}}
124 logging.info("%s: disconnecting", _id)
125 if msg_expected == "text":
126 IN_QUEUES[peer_name].put(None)
127 writer.close()
PrĂłtacal slĂĄn
TĂĄ sĂ© in am againn ĂĄr gcumarsĂĄid a dhaingniĂș. Cad atĂĄ i gceist againn le slĂĄndĂĄil agus cad atĂĄ uainn:
- rĂșndacht na dteachtaireachtaĂ tarchurtha;
- barĂĄntĂșlacht agus slĂĄine na dteachtaireachtaĂ tarchurtha - nĂ mĂłr a n-athruithe a bhrath;
- cosaint i gcoinne ionsaithe athimeartha - nĂ mĂłr teachtaireachtaĂ ar iarraidh nĂł arĂs agus arĂs eile a bhrath (agus socraĂmid deireadh a chur leis an nasc);
- aithint agus fĂordheimhniĂș idirghabhĂĄlaithe ag baint ĂșsĂĄide as eochracha poiblĂ rĂ©amhiontrĂĄilte - shocraigh muid cheana fĂ©in go raibh muid ag dĂ©anamh lĂonra cara le cara. Is tar Ă©is fĂordheimhnithe amhĂĄin a thuigfimid cĂ© leis a bhfuilimid i mbun cumarsĂĄide;
- infhaighteacht
rĂșndacht tosaigh foirfe rĂ©admhaoin (PFS) - nĂor cheart go mbeifĂ in ann gach comhfhreagras roimhe seo a lĂ©amh mĂĄ chuirtear ĂĄr n-eochair sĂnithe fadchĂłnaithe i mbaol. NĂ dhĂ©anfaidh aon mhaith trĂĄcht a thaifeadadh; - bailĂocht/bailĂocht teachtaireachtaĂ (iompar agus croitheadh ââlĂĄimhe) laistigh de sheisiĂșn TCP amhĂĄin. NĂor cheart go mbeadh sĂ© indĂ©anta teachtaireachtaĂ sĂnithe/fĂordheimhnithe i gceart Ăł sheisiĂșn eile a chur isteach (fiĂș leis an idirghabhĂĄlaĂ cĂ©anna);
- nĂor cheart do bhreathnadĂłir Ă©ighnĂomhach aitheantĂłirĂ ĂșsĂĄideora, eochracha poiblĂ fadsaoil a tharchur, nĂł hashes uathu a fheiceĂĄil. Ainm ĂĄirithe Ăł bhreathnadĂłir Ă©ighnĂomhach.
Is ĂĄbhar iontais Ă© gur mian le beagnach gach duine an t-ĂosmhĂ©id seo a bheith acu in aon phrĂłtacal croitheadh ââlĂĄimhe, agus is beag an mĂ©id thuas a chomhlĂontar i ndeireadh na dĂĄla le haghaidh prĂłtacail âdĂșchaisâ. Anois nĂ dhĂ©anfaimid aon rud nua a chumadh. Ba mhaith liom a mholadh cinnte a ĂșsĂĄid
Is iad an dĂĄ phrĂłtacal is coitianta nĂĄ:
TLS - prĂłtacal an-chasta le stair fhada de fhabhtanna, subha, leochaileachtaĂ, droch-mhachnamh, castacht agus easnaimh (ach is beag an bhaint atĂĄ aige seo le TLS 1.3). Ach nĂ mheasaimid Ă© toisc go bhfuil sĂ© rĂł-chasta.-
IPsec ŃIKE - nach bhfuil fadhbanna cripteagrafacha tromchĂșiseacha acu, cĂ© nach bhfuil siad simplĂ freisin. MĂĄ lĂ©ann tĂș faoi IKEv1 agus IKEv2, is Ă© an fhoinse atĂĄ acuSTS PrĂłtacail , ISO/IEC IS 9798-3 agus SIGMA (SIGn-agus-MAc) - simplĂ go leor le cur i bhfeidhm trĂĄthnĂłna amhĂĄin.
Cad atĂĄ go maith faoi SIGMA, mar an nasc is dĂ©anaĂ i bhforbairt prĂłtacail STS/ISO? ComhlĂonann sĂ© ĂĄr gcuid riachtanas go lĂ©ir (lena n-ĂĄirĂtear aitheantĂłirĂ idirghabhĂĄlaĂ a âbhfolĂșâ) agus nĂl aon fhadhbanna cripteagrafacha aitheanta aige. TĂĄ sĂ© Ăostach - mĂĄ bhaintear eilimint amhĂĄin ar a laghad as an teachtaireacht prĂłtacail beidh sĂ© ina chĂșis le neamhshlĂĄndĂĄil.
Rachaimid Ăłn bprĂłtacal baile is simplĂ go SIGMA. Is Ă© an oibrĂocht is bunĂșsaĂ a bhfuil suim againn ann
âââââââ âââââââ â PeerAâ âPeerBâ âââââââ âââââââ â âââââââââââ âââââââââââ âââââââââââââââ>â â(PrvA, PrvA) â â ââââââââ ââââââââââââ â IdB, PubB â ââââââââââââââââ âââââââââ âââââââ âPrvB, PubB = DHgen() â â â ââââââââââââââââ â âââ âââââ ââââ§âââââââââââââ â â Eochair = DH(PrvA, PubB)â <ââââ ââ âââââââ âââââ â â â â
Is fĂ©idir le duine ar bith lĂ©im sa lĂĄr agus a gcuid eochracha poiblĂ fĂ©in a athsholĂĄthar - nĂl aon fhĂordheimhniĂș idirghabhĂĄlaithe sa phrĂłtacal seo. Cuirimis sĂniĂș le heochracha fadsaoil leis.
âââââââ âââââââ â PeerAâ âPeerBâ ââââŹâââ ââââ âââ SignPrvA, (PubA)) â ââ ClĂĄraigh A = ualach() â â â â PrvA, PubA = DHgen() â â â âââââââââ ââââââ âââââââââââââ â, comhartha (SignPrvB, (PubB)) â ââââââââââââââââ ââââââ ââââââââââ ââââââ âââââââ ââââââââââ ââââââââââââââ ââ â SignPrvB, SignPubB = ualach( )â â â â PrvB, PubB â â â â â PrvB, PubB = â âââââââââ âââââââââââââââ ââ âââââ â ââââââââ ââââââ â â âfĂoraigh( SignPubB, ...) â â <ââââ â Eochair = DH(PrvA , PubB) â â â âââââââââââââââ â ââ â â â
NĂ oibreoidh sĂniĂș den sĂłrt sin, Ăłs rud Ă© nach bhfuil sĂ© ceangailte le seisiĂșn ar leith. TĂĄ teachtaireachtaĂ dĂĄ leithĂ©id âoiriĂșnachâ freisin do sheisiĂșin le rannphĂĄirtithe eile. NĂ mĂłr don chomhthĂ©acs iomlĂĄn sĂntiĂșs a Ăoc. Cuireann sĂ© seo iallach orainn teachtaireacht eile Ăł A a chur leis freisin.
Ina theannta sin, tĂĄ sĂ© rĂthĂĄbhachtach d'aitheantĂłir fĂ©in a chur leis faoin sĂniĂș, mar ar shlĂ eile is fĂ©idir linn IdXXX a ionadĂș agus an teachtaireacht a athshĂniĂș le heochair idirghabhĂĄlaĂ aitheanta eile. Chun cosc ââa chur
âââââââ âââââââ â PeerAâ âPeerBâ âââââââ âââââââ â âââââââââââ ââââââââââââââââââ âââââââââââââââââââââââ ââââââââââ âââââââââââââ>â â SignPrvA, SignPubA = ualach()â â â â PrvA, PubA = DHgen() â â â â ââââââ ââââââââââââââââ âIdB, PubB, comhartha(ComharthaPrvB, (IdB, PubA, PubB)) â â â â âââââ âââââââââââââ â<âââââââââââââââââââââââ âââââââââ ââââââââââ â SignPrvB, SignPubB = ualach() â â â â PrvB, PubB = DHgen() â â â â â â â â â âââââââ âââââââââââ â comhartha(SignPrvA, (IDA, PubB, PubA)) â ââââââââ â ââââââ ââââââ ââââââââââââââââââââââââââââââââââââââââââ ââ>â âfĂoraigh(SignPubB, ...) â â â âEochair = DH(PrvA, PubB) â â â âââââââââââââââââ âââ â
Mar sin fĂ©in, nĂl "cruthĂș" fĂłs againn go bhfuil an eochair chomhroinnte chĂ©anna ginte againn don seisiĂșn seo. I bprionsabal, is fĂ©idir linn a dhĂ©anamh gan an chĂ©im seo - beidh an chĂ©ad nasc iompair neamhbhailĂ, ach ba mhaith linn nuair a bheidh an croitheadh ââlĂĄimhe crĂochnaithe, ba mhaith linn a bheith cinnte go bhfuil gach rud aontaithe i ndĂĄirĂre. Faoi lĂĄthair tĂĄ an prĂłtacal ISO/IEC IS 9798-3 idir lĂĄmha againn.
DâfhĂ©adfaimis an eochair ghinte fĂ©in a shĂniĂș. TĂĄ sĂ© seo contĂșirteach, Ăłs rud Ă© go bhfĂ©adfadh sceitheadh ââa bheith ann san algartam sĂnithe a ĂșsĂĄidtear (cĂ© go giotĂĄn in aghaidh an tsĂnithe, ach fĂłs sceitheanna). Is fĂ©idir hash den eochair dĂorthaithe a shĂniĂș, ach dâfhĂ©adfadh sĂ© a bheith luachmhar mĂĄ sceitheadh ââfiĂș hash na heochrach dĂorthaithe in ionsaĂ brĂșidiĂșil ar an bhfeidhm dĂorthaithe. ĂsĂĄideann SIGMA feidhm MAC a fhĂordheimhnĂonn aitheantas an tseoltĂłra.
âââââââ âââââââ â PeerAâ âPeerBâ âââââââ âââââââ â âââââââââââ ââââââââââââââââââ âââââââââââââââââââââââ ââââââââââ ââââââââââââââââââ>â â SignPrvA, SignPubA = ualach() â â â â Prv = A â â â Prv â â ââââââ âââââââââââââââ ââââââ âIdB, PubB, comhartha(SignPrvB, (PubA, PubB) â) âââ ââââââââââââââââââââââ<âââââââââââââââââââ âââââââââ ââââââââââââââââââââââ â SignPrvB, SignPubB = ualach() â â â â B â â â â â â â â â â â â â â â â â â â â â â â âââââ â âââââââââââââââââââââââ â âââââââââââ comhartha âââââââââ â comhartha (ComharthaPrvA, (PubB, PubA)), MAC(IDA) â âEochair = DH(PrvA, PubB) â â âââââââââââââââââââââââââââââââââââââââ â â âââââââââââââââââââââââââ>â âââââââââââââââââââ>â âfĂoraigh(Eochair, IdB) â â â â â â â â â â â â ââââââââââââââââââââââ â â
Mar leas iomlĂĄn a bhaint, b'fhĂ©idir gur mhaith le cuid acu a n-eochracha gearrshaolacha a athĂșsĂĄid (rud atĂĄ, ar ndĂłigh, trua do PFS). Mar shampla, ghin muid eochairphĂ©ire, rinneamar iarracht nascadh, ach nĂ raibh TCP ar fĂĄil nĂł cuireadh isteach air ĂĄit Ă©igin i lĂĄr an phrĂłtacail. Is mĂłr an nĂĄire acmhainnĂ eantrĂłpachta agus prĂłiseĂĄlaithe a chur amĂș ar phĂ©ire nua. Mar sin, tabharfaimid isteach an fianĂĄn mar a thugtar air - luach brĂ©agach randamach a chosnĂłidh i gcoinne ionsaithe athimeartha randamacha a d'fhĂ©adfadh a bheith ann agus eochracha poiblĂ gearrthĂ©armacha ĂĄ n-athĂșsĂĄid. Mar gheall ar an gceangal idir an fianĂĄn agus an eochair phoiblĂ ghearrshaolach, is fĂ©idir eochair phoiblĂ an phĂĄirtĂ eile a bhaint den sĂniĂș mar rud nach gĂĄ.
âââââââ âââââââ âPeerAâ âPeerBâ âââââââââââ ââââ ââââ A â âââââââââ ââââââââââââââââââââ ââââââââââââââââââââââ ââââââââââ ââââââââââââââââââââââââââââââââââââââââââ >â âSignPrvA, SignPubA = ualach( )â â â â PrvA, PubA = DHgen() â â â âââââââââââââââââââââ â ââ âIdB, PubB, CookieB , comhartha(SignPrvB, (CookieA, CookieB, PubB)), MAC(IdB) â âââââââââââââââââââââââ â â< ââââââââââââââââââââââââââââââââââââââââââ âââââââââ âââââââââââââââââââââ â SignPrvB, SignPubB = ualach() â â â â B â â â B â â â B â â B â â â B â â â B â â âââââââ ââââââââââââââââââââââ â â ââââââââââââ comhartha âââââââ â comhartha( SignPrvA, (FianĂĄnB, FianĂĄnA, PubA)), MAC(IdA) â â Eochair = DH(PrvA, PubB) â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â ââââââââââââââââââââââââââââââââââââââââââ ââââââ>â â fĂoraigh(Eochair, IdB) â â â âfĂoraigh(SignPubB,...) â â â ââââââââââââââââââ â
Ar deireadh, ba mhaith linn prĂobhĂĄideacht ĂĄr gcomhphĂĄirtithe comhrĂĄ a fhĂĄil Ăł bhreathnadĂłir Ă©ighnĂomhach. Chun seo a dhĂ©anamh, tĂĄ sĂ© beartaithe ag SIGMA eochracha gearrshaolacha a mhalartĂș ar dtĂșs agus eochair choiteann a fhorbairt ar a bhfĂ©adfaĂ fĂordheimhniĂș agus aithint teachtaireachtaĂ a chriptiĂș. DĂ©anann SIGMA cur sĂos ar dhĂĄ rogha:
- SIGMA-I - cosnaĂonn sĂ© an tionscnĂłir Ăł ionsaithe gnĂomhacha, an freagrĂłir Ăł ionsaithe Ă©ighnĂomhacha: fĂordheimhnĂonn an tionscnĂłir an freagrĂłir agus mura n-oireann rud Ă©igin, nĂ thugann sĂ© aitheantas dĂł. Tugann an cosantĂłir a aitheantas mĂĄ chuirtear tĂșs le prĂłtacal gnĂomhach leis. NĂ fhoghlaimĂonn an breathnĂłir Ă©ighnĂomhach rud ar bith;
SIGMA-R - a chosnaĂonn an freagrĂłir Ăł ionsaithe gnĂomhacha, an tionscnĂłir Ăł na cinn Ă©ighnĂomhacha. TĂĄ gach rud dĂreach ina coinne, ach sa phrĂłtacal seo tĂĄ ceithre theachtaireacht chroitheadh ââlĂĄimhe tarchurtha cheana fĂ©in.Roghnaimid SIGMA-I mar go bhfuil sĂ© nĂos cosĂșla leis an mĂ©id a bhfuil sĂșil againn Ăł rudaĂ eolach cliant-freastalaĂ: is Ă© an freastalaĂ fĂordheimhnithe amhĂĄin a aithnĂtear an cliant, agus tĂĄ a fhios ag gach duine ar an bhfreastalaĂ cheana fĂ©in. Ina theannta sin tĂĄ sĂ© nĂos Ă©asca Ă© a chur i bhfeidhm mar gheall ar nĂos lĂș teachtaireachtaĂ croith lĂĄimhe. Is Ă© an t-aon rud a chuirimid leis an bprĂłtacal nĂĄ cuid den teachtaireacht a chriptiĂș agus an t-aitheantĂłir A a aistriĂș go dtĂ an chuid criptithe den teachtaireacht dheireanach:
âââââââ âââââââ âPeerAâ âPeerBâ ââââŹâââ âââ â â ââ â âââââââââââ ââââââââââââââââââ âââââââââââââââââââââââ ââââââââââ ââââââââââââââââââââââââââââââââââââââââââ âââââ>â â SignPrvA , SignPubA = ualach() â â â â PrvA, PubA = DHgen() â â â ââââââââââââââââââââââââ âââââ â PubB, FianĂĄnB, Enc((IdB, comhartha(SignPrvB, (CookieA, CookieB, PubB)), MAC(IdB)))) â â â ââ â â â â â â â â â â â â â â â â â â â âââââââââ<ââââââââââââââââââââââââââââ âââââââââ âSignPrv B, SignPubB = ualach()â â â â PrvB, PubB = DHgen() â â â ââââââââââââ âââââââ ââ â â â ââââââââ ââââââââââââââ â Enc(Avie, Cook, Sign(Avie), Enc(Avie,Cook) MAC(IDA) )) â âEochair = DH(PrvA, PubB) â âââââââââââââââââââââââââââ ââââââ ââââ âââââââââ ââââââââââââââââââââââââââââ â>â âfĂoraigh(Eochair, IdB) â â â âfĂoraigh(ClĂĄraigh TĂĄbhairne,...)â â â âââââââââââââââââââ
- ĂsĂĄidtear GOST R le haghaidh sĂniĂș
34.10-2012 algartam le heochracha 256-giotĂĄn. - Chun an eochair phoiblĂ a ghiniĂșint, ĂșsĂĄidtear 34.10/2012/XNUMX VKO.
- ĂsĂĄidtear CMAC mar an MAC. Go teicniĂșil, is modh oibrĂochta speisialta Ă© seo de bhloc-sipher, a thuairiscĂtear i GOST R 34.13-2015. Mar fheidhm criptithe don mhĂłd seo -
DreoilĂn teaspaigh (34.12-2015). - ĂsĂĄidtear hash a eochair phoiblĂ mar aitheantĂłir an idirghabhĂĄlaĂ. ĂsĂĄidte mar hash
Streachailt-256 (34.11/2012/256 XNUMX giotĂĄn).
Tar Ă©is an chroitheadh ââlĂĄimhe, comhaontĂłidh muid ar eochair roinnte. Is fĂ©idir linn Ă© a ĂșsĂĄid chun teachtaireachtaĂ iompair a chriptiĂș fĂordheimhnithe. TĂĄ an chuid seo an-simplĂ agus deacair botĂșn a dhĂ©anamh: dĂ©anaimid an cuntar teachtaireachta a incrimint, an teachtaireacht a chriptiĂș, an cuntar agus an ciphertext a fhĂordheimhniĂș (MAC), seol. Nuair a fhaigheann muid teachtaireacht, dĂ©anaimid seiceĂĄil go bhfuil an luach ionchais ag an gcuntar, fĂordheimhnigh an ciphertext leis an gcuntar, agus dĂchriptigh Ă©. CĂ©n eochair ba cheart dom a ĂșsĂĄid chun teachtaireachtaĂ croitheadh ââlĂĄimhe a chriptiĂș, teachtaireachtaĂ a iompar, agus conas iad a fhĂordheimhniĂș? TĂĄ sĂ© contĂșirteach agus mĂ-chiallmhar ĂșsĂĄid a bhaint as eochair amhĂĄin do na tascanna seo go lĂ©ir. Is gĂĄ eochracha a ghiniĂșint ag baint ĂșsĂĄide as feidhmeanna speisialaithe
KDF (feidhm dĂorthaithe eochair). ArĂs, nĂĄ scoiltimis ribĂ agus dĂ©anaimis rud Ă©igin:HKDF le fada an lĂĄ, taighde maith agus nĂl aon fadhbanna aitheanta. Ar an drochuair, nĂl an fheidhm seo ag leabharlann dĂșchais Python, mar sin ĂșsĂĄidimidhkdf mĂĄla plaisteach. ĂsĂĄideann HKDF go hinmheĂĄnachHMAC , a ĂșsĂĄideann feidhm hash ar a seal. NĂ thĂłgann sĂ© ach cĂșpla lĂne cĂłd mar shampla forfheidhmiĂș i Python ar an leathanach VicipĂ©id. Mar a tharla i gcĂĄs 34.10/2012/256, ĂșsĂĄidfimid Stribog-XNUMX mar fheidhm hash. Tabharfar an eochair seisiĂșin ar aschur ĂĄr bprĂomhfheidhm comhaontaithe, Ăłna nginfear na cinn simĂ©adracha atĂĄ in easnamh:kdf = Hkdf(None, key_session, hash=GOST34112012256) kdf.expand(b"handshake1-mac-identity") kdf.expand(b"handshake1-enc") kdf.expand(b"handshake1-mac") kdf.expand(b"handshake2-mac-identity") kdf.expand(b"handshake2-enc") kdf.expand(b"handshake2-mac") kdf.expand(b"transport-initiator-enc") kdf.expand(b"transport-initiator-mac") kdf.expand(b"transport-responder-enc") kdf.expand(b"transport-responder-mac")
StruchtĂșir/ScĂ©imeanna
BreathnaĂmid ar na struchtĂșir ASN.1 atĂĄ againn anois chun na sonraĂ seo go lĂ©ir a tharchur:
class Msg(Choice): schema = (( ("text", MsgText()), ("handshake0", MsgHandshake0(expl=tag_ctxc(0))), ("handshake1", MsgHandshake1(expl=tag_ctxc(1))), ("handshake2", MsgHandshake2(expl=tag_ctxc(2))), )) class MsgText(Sequence): schema = (( ("payload", MsgTextPayload()), ("payloadMac", MAC()), )) class MsgTextPayload(Sequence): schema = (( ("nonce", Integer(bounds=(0, float("+inf")))), ("ciphertext", OctetString(bounds=(1, MaxTextLen))), )) class MsgHandshake0(Sequence): schema = (( ("cookieInitiator", Cookie()), ("pubKeyInitiator", PubKey()), )) class MsgHandshake1(Sequence): schema = (( ("cookieResponder", Cookie()), ("pubKeyResponder", PubKey()), ("ukm", OctetString(bounds=(8, 8))), ("ciphertext", OctetString()), ("ciphertextMac", MAC()), )) class MsgHandshake2(Sequence): schema = (( ("ciphertext", OctetString()), ("ciphertextMac", MAC()), )) class HandshakeTBE(Sequence): schema = (( ("identity", OctetString(bounds=(32, 32))), ("signature", OctetString(bounds=(64, 64))), ("identityMac", MAC()), )) class HandshakeTBS(Sequence): schema = (( ("cookieTheir", Cookie()), ("cookieOur", Cookie()), ("pubKeyOur", PubKey()), )) class Cookie(OctetString): bounds = (16, 16) class PubKey(OctetString): bounds = (64, 64) class MAC(OctetString): bounds = (16, 16)
Is Ă© HandshakeTBS an rud a shĂneofar. HandshakeTBE - cad a bheidh criptithe. DĂrĂm dâaird ar an rĂ©imse ukm in MsgHandshake1. 34.10 ĂirĂtear VKO, le haghaidh randamachĂș nĂos mĂł fĂłs ar na heochracha ginte, paraimĂ©adar UKM (ĂĄbhar eochrach ĂșsĂĄideora) - gan ach eantrĂłpacht bhreise.
CripteagrafaĂocht a Chur leis an gCĂłd
DĂ©anaimis machnamh ach ar na hathruithe a rinneadh ar an gcĂłd bunaidh, Ăłs rud Ă© gur fhan an creat mar an gcĂ©anna (go deimhin, scrĂobhadh an cur i bhfeidhm deiridh ar dtĂșs, agus ansin gearradh an cripteagrafaĂocht go lĂ©ir as).
Ăs rud Ă© go ndĂ©anfar fĂordheimhniĂș agus sainaithint idirghabhĂĄlaithe ag baint ĂșsĂĄide as eochracha poiblĂ, nĂ mĂłr iad a stĂłrĂĄil anois in ĂĄit Ă©igin ar feadh i bhfad. Ar mhaithe le simplĂocht, ĂșsĂĄidimid JSON mar seo:
{ "our": { "prv": "21254cf66c15e0226ef2669ceee46c87b575f37f9000272f408d0c9283355f98", "pub": "938c87da5c55b27b7f332d91b202dbef2540979d6ceaa4c35f1b5bfca6df47df0bdae0d3d82beac83cec3e353939489d9981b7eb7a3c58b71df2212d556312a1" }, "their": { "alice": "d361a59c25d2ca5a05d21f31168609deeec100570ac98f540416778c93b2c7402fd92640731a707ec67b5410a0feae5b78aeec93c4a455a17570a84f2bc21fce", "bob": "aade1207dd85ecd283272e7b69c078d5fae75b6e141f7649ad21962042d643512c28a2dbdc12c7ba40eb704af920919511180c18f4d17e07d7f5acd49787224a" } }
ĂĄr - ĂĄr bpĂ©ire eochair, eochracha heicsidheacha, prĂobhĂĄideacha agus poiblĂ. â ainmneacha na n-idirghabhĂĄlaithe agus a n-eochracha poiblĂ. AthraĂmis na hargĂłintĂ lĂne ordaithe agus cuirimis iarphrĂłiseĂĄil sonraĂ JSON leis:
from pygost import gost3410 from pygost.gost34112012256 import GOST34112012256 CURVE = gost3410.GOST3410Curve( *gost3410.CURVE_PARAMS["GostR3410_2001_CryptoPro_A_ParamSet"] ) parser = argparse.ArgumentParser(description="GOSTIM") parser.add_argument( "--keys-gen", action="store_true", help="Generate JSON with our new keypair", ) parser.add_argument( "--keys", default="keys.json", required=False, help="JSON with our and their keys", ) parser.add_argument( "--bind", default="::1", help="Address to listen on", ) parser.add_argument( "--port", type=int, default=6666, help="Port to listen on", ) args = parser.parse_args() if args.keys_gen: prv_raw = urandom(32) pub = gost3410.public_key(CURVE, gost3410.prv_unmarshal(prv_raw)) pub_raw = gost3410.pub_marshal(pub) print(json.dumps({ "our": {"prv": hexenc(prv_raw), "pub": hexenc(pub_raw)}, "their": {}, })) exit(0) # Parse and unmarshal our and their keys {{{ with open(args.keys, "rb") as fd: _keys = json.loads(fd.read().decode("utf-8")) KEY_OUR_SIGN_PRV = gost3410.prv_unmarshal(hexdec(_keys["our"]["prv"])) _pub = hexdec(_keys["our"]["pub"]) KEY_OUR_SIGN_PUB = gost3410.pub_unmarshal(_pub) KEY_OUR_SIGN_PUB_HASH = OctetString(GOST34112012256(_pub).digest()) for peer_name, pub_raw in _keys["their"].items(): _pub = hexdec(pub_raw) KEYS[GOST34112012256(_pub).digest()] = { "name": peer_name, "pub": gost3410.pub_unmarshal(_pub), } # }}}
Is uimhir randamach Ă eochair phrĂobhĂĄideach an algartam 34.10. MĂ©id 256-giotĂĄn le haghaidh cuair Ă©ilipseacha 256-giotĂĄn. NĂ oibrĂonn PyGOST le sraith beart, ach le
lĂon mĂłr , mar sin nĂ mĂłr ĂĄr n-eochair phrĂobhĂĄideach (urandom(32)) a thiontĂș go huimhir ag baint ĂșsĂĄide as gost3410.prv_unmarshal(). Cinntear an eochair phoiblĂ go cinntitheach Ăłn eochair phrĂobhĂĄideach ag baint ĂșsĂĄide as gost3410.public_key(). Is Ă© atĂĄ san eochair phoiblĂ 34.10 nĂĄ dhĂĄ uimhir mhĂłra ar gĂĄ iad a thiontĂș ina seicheamh beart freisin ar mhaithe le hĂ©ascaĂocht stĂłrĂĄla agus tarchurtha ag baint ĂșsĂĄide as gost3410.pub_marshal().Tar Ă©is an comhad JSON a lĂ©amh, nĂ mĂłr na heochracha poiblĂ a thiontĂș ar ais dĂĄ rĂ©ir sin trĂ ĂșsĂĄid a bhaint as gost3410.pub_unmarshal(). Ăs rud Ă© go bhfaighfimid aitheantĂłirĂ na n-idirghabhĂĄlaithe i bhfoirm hash Ăłn eochair phoiblĂ, is fĂ©idir iad a rĂomh lĂĄithreach roimh rĂ© agus a chur i bhfoclĂłir le haghaidh cuardach tapa. TĂĄ hash Stribog-256 gost34112012256.GOST34112012256(), a shĂĄsaĂonn go hiomlĂĄn comhĂ©adan hashlib na bhfeidhmeanna hash.
Conas a d'athraigh coroutine an tionscnĂłra? TĂĄ gach rud de rĂ©ir na scĂ©ime croith lĂĄimhe: gineann muid fianĂĄn (tĂĄ 128-giotĂĄn go leor), pĂ©ire eochair gearrshaolach 34.10, a ĂșsĂĄidfear le haghaidh feidhm chomhaontaithe eochair VKO.
395 async def initiator(host, port): 396 _id = repr((host, port)) 397 logging.info("%s: dialing", _id) 398 reader, writer = await asyncio.open_connection(host, port) 399 # Generate our ephemeral public key and cookie, send Handshake 0 message {{{ 400 cookie_our = Cookie(urandom(16)) 401 prv = gost3410.prv_unmarshal(urandom(32)) 402 pub_our = gost3410.public_key(CURVE, prv) 403 pub_our_raw = PubKey(gost3410.pub_marshal(pub_our)) 404 writer.write(Msg(("handshake0", MsgHandshake0(( 405 ("cookieInitiator", cookie_our), 406 ("pubKeyInitiator", pub_our_raw), 407 )))).encode()) 408 # }}} 409 await writer.drain()
- tĂĄimid ag fanacht le freagra agus dĂchĂłdaithe an teachtaireacht Msg isteach;
- dĂ©an cinnte go bhfaigheann tĂș croitheadh ââlĂĄimhe1;
- eochair phoiblĂ ghearrshaolach an phĂĄirtĂ eile a dhĂchĂłdĂș agus eochair an tseisiĂșin a rĂomh;
- Gineann muid eochracha siméadracha atå riachtanach chun an chuid TBE den teachtaireacht a phróiseåil.
423 logging.info("%s: got %s message", _id, msg.choice) 424 if msg.choice != "handshake1": 425 logging.warning("%s: unexpected message, disconnecting", _id) 426 writer.close() 427 return 428 # }}} 429 msg_handshake1 = msg.value 430 # Validate Handshake message {{{ 431 cookie_their = msg_handshake1["cookieResponder"] 432 pub_their_raw = msg_handshake1["pubKeyResponder"] 433 pub_their = gost3410.pub_unmarshal(bytes(pub_their_raw)) 434 ukm_raw = bytes(msg_handshake1["ukm"]) 435 ukm = ukm_unmarshal(ukm_raw) 436 key_session = kek_34102012256(CURVE, prv, pub_their, ukm, mode=2001) 437 kdf = Hkdf(None, key_session, hash=GOST34112012256) 438 key_handshake1_mac_identity = kdf.expand(b"handshake1-mac-identity") 439 key_handshake1_enc = kdf.expand(b"handshake1-enc") 440 key_handshake1_mac = kdf.expand(b"handshake1-mac")
Is uimhir 64-giotĂĄn Ă UKM (urandom(8)), a Ă©ilĂonn freisin dĂshraithiĂș Ăłna lĂ©iriĂș beart ag baint ĂșsĂĄide as gost3410_vko.ukm_unmarshal(). Is Ă© feidhm VKO le haghaidh 34.10/2012/256 3410-giotĂĄn nĂĄ gost34102012256_vko.kek_XNUMX() (KEK - eochair criptithe).
Is seicheamh beart randamach randamach 256-giotĂĄn an eochair seisiĂșin a ghintear cheana fĂ©in. Mar sin, is fĂ©idir Ă© a ĂșsĂĄid lĂĄithreach i bhfeidhmeanna HKDF. Ăs rud Ă© go sĂĄsaĂonn GOST34112012256 an comhĂ©adan hashlib, is fĂ©idir Ă© a ĂșsĂĄid lĂĄithreach sa rang Hkdf. NĂ shonraĂonn muid an salann (an chĂ©ad argĂłint Hkdf), Ăłs rud Ă© go mbeidh an eochair a ghintear, mar gheall ar thrasfhoirmiĂșlacht na bpĂ©irĂ eochair rannphĂĄirteacha, difriĂșil do gach seisiĂșn agus go bhfuil go leor eantrĂłpachta ann cheana fĂ©in. kdf.expand() de rĂ©ir rĂ©amhshocraithe tĂĄirgeann sĂ© na heochracha 256-giotĂĄn atĂĄ ag teastĂĄil le haghaidh DreoilĂn teaspaigh nĂos dĂ©anaĂ.
Ansin, déantar na codanna TBE agus TBS den teachtaireacht isteach a sheiceåil:
- dĂ©antar an MAC thar an tĂ©acs ciphersa isteach a rĂomh agus a sheiceĂĄil;
- tĂĄ an ciphertext dĂchriptithe;
- TĂĄ struchtĂșr TBE dĂchĂłdaithe;
- tógtar aitheantóir an idirghabhålaà uaidh agus seiceåiltear an bhfuil sé ar eolas againn ar chor ar bith;
- DĂ©antar MAC thar an aitheantĂłir seo a rĂomh agus a sheiceĂĄil;
- dĂ©antar an sĂniĂș thar an struchtĂșr TBS a fhĂorĂș, lena n-ĂĄirĂtear fianĂĄn an dĂĄ phĂĄirtĂ agus eochair ghearrshaolach phoiblĂ an phĂĄirtĂ eile. FĂoraĂtear an sĂniĂș le heochair shĂnithe fhadtĂ©armach an idirghabhĂĄlaĂ.
441 try: 442 peer_name = validate_tbe( 443 msg_handshake1, 444 key_handshake1_mac_identity, 445 key_handshake1_enc, 446 key_handshake1_mac, 447 cookie_our, 448 cookie_their, 449 pub_their_raw, 450 ) 451 except ValueError as err: 452 logging.warning("%s: %s, disconnecting", _id, err) 453 writer.close() 454 return 455 # }}} 128 def validate_tbe( 129 msg_handshake: Union[MsgHandshake1, MsgHandshake2], 130 key_mac_identity: bytes, 131 key_enc: bytes, 132 key_mac: bytes, 133 cookie_their: Cookie, 134 cookie_our: Cookie, 135 pub_key_our: PubKey, 136 ) -> str: 137 ciphertext = bytes(msg_handshake["ciphertext"]) 138 mac_tag = mac(GOST3412Kuznechik(key_mac).encrypt, KUZNECHIK_BLOCKSIZE, ciphertext) 139 if not compare_digest(mac_tag, bytes(msg_handshake["ciphertextMac"])): 140 raise ValueError("invalid MAC") 141 plaintext = ctr( 142 GOST3412Kuznechik(key_enc).encrypt, 143 KUZNECHIK_BLOCKSIZE, 144 ciphertext, 145 8 * b"x00", 146 ) 147 try: 148 tbe, _ = HandshakeTBE().decode(plaintext) 149 except ASN1Error: 150 raise ValueError("can not decode TBE") 151 key_sign_pub_hash = bytes(tbe["identity"]) 152 peer = KEYS.get(key_sign_pub_hash) 153 if peer is None: 154 raise ValueError("unknown identity") 155 mac_tag = mac( 156 GOST3412Kuznechik(key_mac_identity).encrypt, 157 KUZNECHIK_BLOCKSIZE, 158 key_sign_pub_hash, 159 ) 160 if not compare_digest(mac_tag, bytes(tbe["identityMac"])): 161 raise ValueError("invalid identity MAC") 162 tbs = HandshakeTBS(( 163 ("cookieTheir", cookie_their), 164 ("cookieOur", cookie_our), 165 ("pubKeyOur", pub_key_our), 166 )) 167 if not gost3410.verify( 168 CURVE, 169 peer["pub"], 170 GOST34112012256(tbs.encode()).digest(), 171 bytes(tbe["signature"]), 172 ): 173 raise ValueError("invalid signature") 174 return peer["name"]
Mar a scrĂobh mĂ© thuas, tĂĄ cur sĂos ar 34.13/2015/XNUMX Ă©agsĂșla
bloc modhanna oibriĂșchĂĄin cipher Ăłn 34.12/2015/3413. Ina measc tĂĄ modh chun iatĂĄin brĂ©ige agus rĂomhanna MAC a ghiniĂșint. I PyGOST is Ă© seo gost34.12.mac(). ĂilĂonn an modh seo an fheidhm criptithe a rith (bloc amhĂĄin sonraĂ a fhĂĄil agus a thabhairt ar ais), mĂ©id an bhloc criptithe agus, go deimhin, na sonraĂ fĂ©in. CĂ©n fĂĄth nach fĂ©idir leat mĂ©id an bhloc criptithe a chĂłdĂș crua? DĂ©anann 2015/128/64 cur sĂos nĂ amhĂĄin ar an XNUMX-giotĂĄn sifir dreoilĂn teaspaigh, ach freisin ar an XNUMX-giotĂĄnMagma - GOST 28147-89 beagĂĄn modhnaithe, a cruthaĂodh ar ais sa KGB agus tĂĄ ceann de na tairseacha sĂĄbhĂĄilteachta is airde fĂłs aige.Cuirtear tĂșs le Kuznechik trĂ ghlao a chur ar gost.3412.GOST3412Kuznechik(eochair) agus cuireann sĂ© rĂ©ad ar ais le modhanna .cript()/.dĂchriptiĂș() atĂĄ oiriĂșnach lena chur ar aghaidh chuig 34.13 feidhmeanna. RĂomhtar MAC mar seo a leanas: gost3413.mac(GOST3412Kuznechik(eochair).cript, KUZNECHIK_BLOCKSIZE, ciphertext). Chun an MAC rĂofa agus faighte a chur i gcomparĂĄid, nĂ fĂ©idir leat an gnĂĄthchomparĂĄid (==) de na teaghrĂĄin bheart a ĂșsĂĄid, Ăłs rud Ă© go sceitheann an oibrĂocht seo am comparĂĄide, rud a d'fhĂ©adfadh, go ginearĂĄlta, leochaileachtaĂ marfach a bheith mar thoradh air.
Beast ionsaithe ar TLS. TĂĄ feidhm speisialta ag Python, hmac.compare_digest, chuige seo.NĂ fĂ©idir leis an bhfeidhm bloc-scipĂ©ir ach bloc amhĂĄin sonraĂ a chriptiĂș. Le haghaidh lĂon nĂos mĂł, agus fiĂș nach iolraĂ den fhad, is gĂĄ an modh criptithe a ĂșsĂĄid. DĂ©anann 34.13-2015 cur sĂos ar na nithe seo a leanas: BCE, CTR, OFB, CBC, CFB. TĂĄ a rĂ©imsĂ iarratais agus trĂ©ithe inghlactha fĂ©in ag gach ceann acu. Ar an drochuair, nĂl caighdeĂĄnaithe againn fĂłs
modhanna criptithe fĂordheimhnithe (cosĂșil le CCM, OCB, GCM agus a leithĂ©id) - tĂĄ iallach orainn ar a laghad MAC a chur orainn fĂ©in. roghnaĂmmĂłd cuntair (CTR): nĂ Ă©ilĂonn sĂ© stuĂĄil le mĂ©id an bhloc, is fĂ©idir Ă© a chomhthreomharĂș, nĂ ĂșsĂĄideann sĂ© ach an fheidhm criptithe, is fĂ©idir Ă© a ĂșsĂĄid go sĂĄbhĂĄilte chun lĂon mĂłr teachtaireachtaĂ a chriptiĂș (murab ionann agus CBC, a bhfuil imbhuailtĂ sĂĄch tapa).Ar nĂłs .mac(), glacann .ctr() ionchur comhchosĂșil: ciphertext = gost3413.ctr(GOST3412Kuznechik(eochair).cript, KUZNECHIK_BLOCKSIZE, gnĂĄththĂ©acs, iv). TĂĄ sĂ© riachtanach veicteoir tosaigh a shonrĂș atĂĄ dĂreach leath fhad an bhloic criptithe. Mura n-ĂșsĂĄidtear ĂĄr n-eochair chriptiĂșchĂĄin ach chun teachtaireacht amhĂĄin a chriptiĂș (cĂ© gur Ăł roinnt bloic), tĂĄ sĂ© sĂĄbhĂĄilte veicteoir tosaigh nialasach a shocrĂș. Chun teachtaireachtaĂ croitheadh ââlĂĄimhe a chriptiĂș, ĂșsĂĄidimid eochair ar leith gach uair.
Is fĂĄnach an sĂniĂș gost3410.verify() a fhĂorĂș: tugaimid thar an gcuar Ă©ilipseach ina bhfuilimid ag obair (nĂ dhĂ©anaimid ach Ă© a thaifeadadh inĂĄr bprĂłtacal GOSTIM), eochair phoiblĂ an sĂnitheoir (nĂĄ dĂ©an dearmad gur chĂłir go mbeadh sĂ© seo ina thuple de dhĂĄ lĂon mĂłr, agus nĂ teaghrĂĄn beart), 34.11/2012/XNUMX hash agus an sĂniĂș fĂ©in.
Ansin, sa thionscnĂłir dĂ©anaimid teachtaireacht chroitheadh ââlĂĄimhe a ullmhĂș agus a sheoladh chuig handshake2, ag dĂ©anamh na ngnĂomhartha cĂ©anna agus a rinneamar le linn an fhĂoraithe, go simĂ©adrach amhĂĄin: sĂniĂș ar ĂĄr n-eochracha in ionad seiceĂĄil, etc..
456 # Prepare and send Handshake 2 message {{{ 457 tbs = HandshakeTBS(( 458 ("cookieTheir", cookie_their), 459 ("cookieOur", cookie_our), 460 ("pubKeyOur", pub_our_raw), 461 )) 462 signature = gost3410.sign( 463 CURVE, 464 KEY_OUR_SIGN_PRV, 465 GOST34112012256(tbs.encode()).digest(), 466 ) 467 key_handshake2_mac_identity = kdf.expand(b"handshake2-mac-identity") 468 mac_tag = mac( 469 GOST3412Kuznechik(key_handshake2_mac_identity).encrypt, 470 KUZNECHIK_BLOCKSIZE, 471 bytes(KEY_OUR_SIGN_PUB_HASH), 472 ) 473 tbe = HandshakeTBE(( 474 ("identity", KEY_OUR_SIGN_PUB_HASH), 475 ("signature", OctetString(signature)), 476 ("identityMac", MAC(mac_tag)), 477 )) 478 tbe_raw = tbe.encode() 479 key_handshake2_enc = kdf.expand(b"handshake2-enc") 480 key_handshake2_mac = kdf.expand(b"handshake2-mac") 481 ciphertext = ctr( 482 GOST3412Kuznechik(key_handshake2_enc).encrypt, 483 KUZNECHIK_BLOCKSIZE, 484 tbe_raw, 485 8 * b"x00", 486 ) 487 mac_tag = mac( 488 GOST3412Kuznechik(key_handshake2_mac).encrypt, 489 KUZNECHIK_BLOCKSIZE, 490 ciphertext, 491 ) 492 writer.write(Msg(("handshake2", MsgHandshake2(( 493 ("ciphertext", OctetString(ciphertext)), 494 ("ciphertextMac", MAC(mac_tag)), 495 )))).encode()) 496 # }}} 497 await writer.drain() 498 logging.info("%s: session established: %s", _id, peer_name)
Nuair a bhĂonn an seisiĂșn bunaithe, gintear eochracha iompair (eochair ar leith le haghaidh criptithe, fĂordheimhnithe, do gach pĂĄirtĂ), agus cuirtear an Grasshopper ar dtĂșs chun an MAC a dhĂchriptiĂș agus a sheiceĂĄil:
499 # Run text message sender, initialize transport decoder {{{ 500 key_initiator_enc = kdf.expand(b"transport-initiator-enc") 501 key_initiator_mac = kdf.expand(b"transport-initiator-mac") 502 key_responder_enc = kdf.expand(b"transport-responder-enc") 503 key_responder_mac = kdf.expand(b"transport-responder-mac") ... 509 asyncio.ensure_future(msg_sender( 510 peer_name, 511 key_initiator_enc, 512 key_initiator_mac, 513 writer, 514 )) 515 encrypter = GOST3412Kuznechik(key_responder_enc).encrypt 516 macer = GOST3412Kuznechik(key_responder_mac).encrypt 517 # }}} 519 nonce_expected = 0 520 # Wait for test messages {{{ 521 while True: 522 data = await reader.read(MaxMsgLen) ... 530 msg, tail = Msg().decode(buf) ... 537 try: 538 await msg_receiver( 539 msg.value, 540 nonce_expected, 541 macer, 542 encrypter, 543 peer_name, 544 ) 545 except ValueError as err: 546 logging.warning("%s: %s", err) 547 break 548 nonce_expected += 1 549 # }}}
CriptĂonn coroutine msg_sender teachtaireachtaĂ anois sula seoltar ar nasc TCP iad. TĂĄ mĂ©adĂș monatonach ag gach teachtaireacht, agus is Ă© sin an veicteoir tosaigh freisin nuair a bhĂonn sĂ© criptithe i mĂłd cuntair. TĂĄ rĂĄthaĂocht ar chuntarluach difriĂșil ag gach teachtaireacht agus bloc teachtaireachta.
async def msg_sender(peer_name: str, key_enc: bytes, key_mac: bytes, writer) -> None: nonce = 0 encrypter = GOST3412Kuznechik(key_enc).encrypt macer = GOST3412Kuznechik(key_mac).encrypt in_queue = IN_QUEUES[peer_name] while True: text = await in_queue.get() if text is None: break ciphertext = ctr( encrypter, KUZNECHIK_BLOCKSIZE, text.encode("utf-8"), long2bytes(nonce, 8), ) payload = MsgTextPayload(( ("nonce", Integer(nonce)), ("ciphertext", OctetString(ciphertext)), )) mac_tag = mac(macer, KUZNECHIK_BLOCKSIZE, payload.encode()) writer.write(Msg(("text", MsgText(( ("payload", payload), ("payloadMac", MAC(mac_tag)), )))).encode()) nonce += 1
DĂ©anann coroutine msg_receiver teachtaireachtaĂ isteach a phrĂłiseĂĄil, a lĂĄimhseĂĄlann fĂordheimhniĂș agus dĂchriptiĂș:
async def msg_receiver( msg_text: MsgText, nonce_expected: int, macer, encrypter, peer_name: str, ) -> None: payload = msg_text["payload"] if int(payload["nonce"]) != nonce_expected: raise ValueError("unexpected nonce value") mac_tag = mac(macer, KUZNECHIK_BLOCKSIZE, payload.encode()) if not compare_digest(mac_tag, bytes(msg_text["payloadMac"])): raise ValueError("invalid MAC") plaintext = ctr( encrypter, KUZNECHIK_BLOCKSIZE, bytes(payload["ciphertext"]), long2bytes(nonce_expected, 8), ) text = plaintext.decode("utf-8") await OUT_QUEUES[peer_name].put(text)
ConclĂșid
TĂĄ GOSTIM beartaithe le hĂșsĂĄid go heisiach chun crĂocha oideachais (Ăłs rud Ă© nach bhfuil sĂ© clĂșdaithe ag tĂĄstĂĄlacha, ar a laghad)! Is fĂ©idir cĂłd foinse an chlĂĄir a ĂoslĂłdĂĄil
anseo (ĐĄŃŃĐžĐ±ĐŸĐł-256 Ń ŃŃ: 995bbd368c04e50a481d138c5fa2e43ec7c89bc77743ba8dbabee1fde45de120). ĐĐ°Đș Đž ĐČŃĐ” ĐŒĐŸĐž ĐżŃĐŸĐ”ĐșŃŃ, ŃОпаGoGOST ,PyDERASN ,NCCP ,GoVPN , tĂĄ GOSTIM go hiomlĂĄnbogearraĂ saor in aisce dhĂĄileadh faoi na tĂ©armaĂGPLv3 + .Sergey Matveev ,cipherpunk , ballFondĂșireacht SPO , Python/Go-forbrĂłir, prĂomhspeisialtĂłirFiontraĂocht StĂĄit ChĂłnaidhme "STC "Atlas" . - ĂsĂĄidtear GOST R le haghaidh sĂniĂș
Foinse: will.com