123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150moduletypeDH=sigtypeprivate_keytypepublic_keyvalkey_size:intvalbase:public_keyvalpublic_key_of_string:string->public_keyvalprivate_key_of_string:string->private_keyvalstring_of_public_key:public_key->stringvalstring_of_private_key:private_key->stringvalscale:private_key->public_key->public_keyvalpublic_key_of_private_key:private_key->public_keyendmoduleX25519:DH=structtypeprivate_key=Private_keyofZ.ttypepublic_key=Public_keyofZ.tletkey_size=32moduleA=structtypeelement=Z.ttypeintegral=Z.tletp=Z.(onelsl255-~$19)letbits=255leta24=Z.of_int121665lettwo=Z.(~$2)letconstant_time_conditional_swapcondab=letc=Z.(remcondtwo)inletc'=Z.(one-c)inleta'=Z.(c'*a+c*b)inletb'=Z.(c'*b+c*a)ina',b'endmoduleC=Curve.Make(Zfield.Zp(A))(Z)(A)(* Quoth the RFC:
set the three least significant bits of the first byte and the most significant bit
of the last to zero, set the second most significant bit of the last byte to 1
*)letsanitize_scalar=letunset_this=Z.logorZ.(~$7)(Z.shift_leftZ.(~$128)(8*31))inletset_that=Z.shift_leftZ.(~$64)(8*31)infunz->Z.(z-(logandzunset_this))|>Z.logorset_thatletpublic_key_of_string:string->public_key=funs->letp=Serde.z_of_hexsinlethigh=Z.(logandp(~$128lsl248))inPublic_keyZ.(p-high)letstring_of_public_key:public_key->string=functionPublic_keypk->Serde.hex_of_zkey_sizepkletprivate_key_of_string:string->private_key=funs->letz=Serde.z_of_hexs|>sanitize_scalarinPrivate_keyzletstring_of_private_key:private_key->string=functionPrivate_keypk->Serde.hex_of_zkey_sizepkletscale(Private_keypriv)(Public_keypub)=Public_key(C.scaleprivpub)letbase=Public_key(Z.of_int9)letpublic_key_of_private_keypriv=scaleprivbaseendletx25519~priv~pub=X25519.(scale(private_key_of_stringpriv)(public_key_of_stringpub)|>string_of_public_key)moduleX448:DH=structtypeprivate_key=Private_keyofZ.ttypepublic_key=Public_keyofZ.tletkey_size=56moduleA=structtypeelement=Z.ttypeintegral=Z.tletp=Z.(onelsl448-onelsl224-~$1)letbits=448leta24=Z.of_int39081lettwo=Z.(~$2)letconstant_time_conditional_swapcondab=letc=Z.(remcondtwo)inletc'=Z.(one-c)inleta'=Z.(c'*a+c*b)inletb'=Z.(c'*b+c*a)ina',b'endmoduleC=Curve.Make(Zfield.Zp(A))(Z)(A)(* Quoth the RFC:
set the two least significant bits of the first byte to 0, and the most
significant bit of the last byte to 1.
*)letsanitize_scalar=letunset_this=Z.(~$3)inletset_that=Z.shift_leftZ.(~$128)(8*55)infunz->Z.(z-(logandzunset_this))|>Z.logorset_thatletpublic_key_of_string:string->public_key=funs->letp=Serde.z_of_hexsinPublic_keypletstring_of_public_key:public_key->string=functionPublic_keypk->Serde.hex_of_zkey_sizepkletprivate_key_of_string:string->private_key=funs->letz=Serde.z_of_hexs|>sanitize_scalarinPrivate_keyzletstring_of_private_key:private_key->string=functionPrivate_keypk->Serde.hex_of_zkey_sizepkletscale(Private_keypriv)(Public_keypub)=Public_key(C.scaleprivpub)letbase=Public_key(Z.of_int5)letpublic_key_of_private_keypriv=scaleprivbaseendletx448~priv~pub=X448.(scale(private_key_of_stringpriv)(public_key_of_stringpub)|>string_of_public_key)