// SPDX-License-Identifier: GPL-3.0-only // Copyright (c) 2022, Sylvain Huet, Ambermind // Minimacy (r) System struct X25519=[_public, _private];; const _P= \big 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed;; const _Pprime= \big 0x2f286bca1af286bca1af286bca1af286bca1af286bca1af286bca1af286bca1b;; const _Pminus2= \big 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb;; const _A24= \big 0x02345d3;; const _One= \big 0x00013;; fun _swapStr(str) = let bytesCreate(32, 0) -> bytes in ( let strLength(str) -> len in for i=0;i bytes in ( let bytesGet(bytes, 0) -> b in bytesSet(bytes, 0, (b&0x7f)|0x40); let bytesGet(bytes, 31) -> b in bytesSet(bytes, 31, b&0xf8); bigDeserializeBytes(bytes) );; fun _decodeU(str) = let _swapStr(str) -> bytes in ( let bytesGet(bytes, 0) -> b in bytesSet(bytes, 0, b&127); bigDeserializeBytes(bytes) );; fun _encodeResult(v)= strFromBytes(_swapStr(bigSerialize(v, 32)));; fun x25519Compute(k, u)= let _decodeScalar(k) -> k in let _decodeU(u) -> u in _encodeResult(bigX25519(_P, _Pprime, _Pminus2, _A24, _One, k, u));; fun _x25519Random()= bigSerialize(bigMod(bigRand(bigNbits(_P), false), _P), 32);; //------------------ API fun x25519FromPublic(public) = [_public=public];; fun x25519FromPrivate(private) = let x25519Compute(private, "\9") -> public in [_public=public, _private=private];; fun x25519Create()= if !randomHardware() then echoLn "> Warning: generate x25519 key with pure software pseudorandom generator"; x25519FromPrivate(_x25519Random());; fun x25519Public(key) = key._public;; fun x25519Private(key) = key._private;; fun x25519IsPrivate(key)= key._private<>nil;; // mix Alice Key with Bob public key to generate the shared secret fun x25519Ecdh(keyAlice, publicBob) = x25519Compute(keyAlice._private, publicBob);;