ABSTRACT (original article): Post-quantum cryptography is essential for securing digital communications against threats posed by quantum computers. Researchers have focused on developing algorithms that can withstand attacks from both classical and quantum computers, thereby ensuring the security of data transmissions over public networks. A critical component of this security is the key agreement protocol, which allows two parties to establish a shared secret key over an insecure channel. This paper introduces two novel post-quantum key agreement protocols that can be easily implemented on standard computers using rectangular or rank-deficient matrices, exploiting the generalizations of the matrix power function, which is a generator of NP-hard problems. We provide basic concepts and proofs, pseudocodes, and examples, along with a discussion of complexity. CITATION (original article): Hecht, J. P., & Scolnik, H. D. (2025). Post-Quantum Key Agreement Protocols Based on Modified Matrix-Power Functions over Singular Random Integer Matrix Semirings. Computer Networks and Communications, 3(1), 1–18. https://doi.org/10.37256/cnc.3120256112
This is a simple, secure and fast program to generate session keys. Obviously in a real production environment, it must be translated into a fast language such as RUST, Java or C++. The algebraic methods on which it is based are sophisticated but easy to use. All details can be found in the published work.
The notebook has two parts, in the first one it generates the keys in numerical form (in matrix format). In the second part, the core of the algorithm used is developed in symbolic form, which allows to appreciate the computational complexity that blocks both classical and quantum cryptanalytic attacks.

Definitions


Multi σ-MPF square rank-deficient BENCH

Generates the keys in numerical form (in matrix format).
In[]:=
Randomize;​​Print["....................................."];​​Print["dim = ",rows=cols=5];​​Print["prime = ",prime=65537];​​Print["Zlimit = ",Zlimit=2^10];​​sigma=RandomInteger[{-Zlimit,+Zlimit}];​​Print["sigma = ",sigma];​​Print["expTop = ",expTop=10];​​Print["total rounds = ",rounds=1];​​Print["verbose = ",verbose=True];​​Print["mini verbose = ",miniverbose=True];​​Print["....................................."];​​(*Wfullrank*)​​W=Rmat;If[verbose,Print["W = ",MatrixForm[W]]];​​BaseXU=RmatDef;If[verbose,Print["BaseXU = ",MatrixForm[BaseXU]]];​​BaseYV=RmatDef;If[verbose,Print["BaseYV = ",MatrixForm[BaseYV]]];​​Print["....................................."];​​Alist=Blist=KeyAlist=KeyBlist={};​​Timing[Module[{round=0,zerokeys=0},​​Label[begin];​​round+=1;​​Label[again];​​X=Mod[MatrixPower[BaseXU,randX=RandomInteger[{2,expTop}]],prime-1];If[verbose,Print["randX = ",randX]];If[verbose,Print["X = ",MatrixForm[X]]];​​Y=Mod[MatrixPower[BaseYV,randY=RandomInteger[{2,expTop}]],prime-1];If[verbose,Print["randY = ",randY]];If[verbose,Print["Y = ",MatrixForm[Y]]];​​U=Mod[MatrixPower[BaseXU,randU=RandomInteger[{2,expTop}]],prime-1];If[verbose,Print["randU = ",randU]];If[verbose,Print["U = ",MatrixForm[U]]];​​V=Mod[MatrixPower[BaseYV,randV=RandomInteger[{2,expTop}]],prime-1];If[verbose,Print["randV = ",randV]];If[verbose,Print["V = ",MatrixForm[V]]];​​A=MPFint[X,W,Y];If[verbose,Print["Token A = ",MatrixForm[A]]];​​Alist=Flatten[Append[Alist,A]];​​If[ANullMatrix,Goto[again]];​​B=MPFint[U,W,V];If[verbose,Print["Token B = ",MatrixForm[B]]];​​If[BNullMatrix,Goto[again]];​​Blist=Flatten[Append[Blist,B]];​​KeyA=MPFint[X,B,Y];If[verbose,Print["KeyA = ",MatrixForm[KeyA]]];​​If[KeyANullMatrix,Goto[begin]];​​KeyB=MPFint[U,A,V];If[verbose,Print["KeyB = ",MatrixForm[KeyB]]];​​If[KeyBNullMatrix,Goto[begin]];​​KeyAlist=Flatten[Append[KeyAlist,KeyA]];​​KeyBlist=Flatten[Append[KeyBlist,KeyB]];​​If[miniverbose,Print["keys agree ? ",KeyAKeyB,"....end of round = ",round]];If[miniverbose,Print["zerokeys = ",zerokeys]];​​If[round<rounds,Goto[begin]];​​]]​​If[verbose,Print["A-Token combined list = ",Alist]];​​If[verbose,Print["Length (numbers) = ",Length[Alist]]];​​If[verbose,Print["B-Token combined list = ",Blist]];​​If[verbose,Print["Length (numbers) = ",Length[Blist]]];​​Print["A-Keys combined list = ",KeyAlist];​​Print["Length (numbers) = ",Length[KeyAlist]];​​Print["B-Keys combined list = ",KeyBlist];​​Print["Length (numbers) = ",Length[KeyBlist]];​​Print["K session key from Alice = ",Hash[KeyAlist,"SHA3-512","HexString"]];​​Print["K session key from Bob = ",Hash[KeyBlist,"SHA3-512","HexString"]];
.....................................
dim = 5
prime = 65537
Zlimit = 1024
sigma = -806
expTop = 10
total rounds = 1
verbose = True
mini verbose = True
.....................................
W =
41697
6151
23262
52928
20614
5676
21811
33623
45340
53343
61042
58833
56804
41789
668
60637
13311
26580
48400
50086
61394
1049
30438
1371
11740
BaseXU =
46720
51449
38914
20462
10656
46720
51449
38914
20462
10656
60437
45705
59501
38633
57401
56999
62679
41221
12429
38072
50382
38044
33734
9703
10423
BaseYV =
89
21802
29582
59064
50633
49736
54349
23099
51946
41545
49736
54349
23099
51946
41545
10112
59634
49093
2639
34525
43025
32273
38261
47271
41217
.....................................
randX = 6
X =
52010
62187
10332
55150
7012
52010
62187
10332
55150
7012
64801
3839
37955
30696
59833
53283
28707
31823
34437
9263
39145
31951
33959
11649
21974
randY = 4
Y =
28873
7404
7823
60954
52229
57549
22914
59540
27329
8802
57549
22914
59540
27329
8802
353
48263
46698
32902
12506
25717
39534
13699
949
20110
randU = 5
U =
31584
10045
55138
46692
16126
31584
10045
55138
46692
16126
43070
7410
38990
54915
59493
56305
20975
53313
1134
24714
17970
28680
43688
57507
32554
randV = 7
V =
41289
54213
4773
20544
3362
51370
27328
34755
31082
63948
51370
27328
34755
31082
63948
16562
64681
27989
48735
8956
58466
37601
22737
46082
54275
Token A =
46148
5279
54674
41606
20857
46148
5279
54674
41606
20857
37287
19632
13311
60086
24268
44682
647
55760
7591
28641
6801
11757
65048
46504
8267
Token B =
16067
49747
5953
28444
5963
16067
49747
5953
28444
5963
14216
10093
24482
26391
424
20479
48558
10694
46525
43719
11722
19309
20064
30593
50794
KeyA =
12795
35494
23840
6271
17390
12795
35494
23840
6271
17390
34099
22115
43780
25140
33482
56338
7456
15812
32860
43719
37196
33376
21272
9198
50284
KeyB =
12795
35494
23840
6271
17390
12795
35494
23840
6271
17390
34099
22115
43780
25140
33482
56338
7456
15812
32860
43719
37196
33376
21272
9198
50284
keys agree ? True....end of round = 1
zerokeys = 0
Out[]=
{6.07813,Null}
A-Token combined list = {46148,5279,54674,41606,20857,46148,5279,54674,41606,20857,37287,19632,13311,60086,24268,44682,647,55760,7591,28641,6801,11757,65048,46504,8267}
Length (numbers) = 25

Symbolic Computation

The core of the algorithm used is developed in symbolic form.

CITE THIS NOTEBOOK

How to arrange a secret between two remote entities resistant to future quantum computer attacks​
by Juan Pedro Hecht and Hugo Daniel Scolnik
Wolfram Community, STAFF PICKS, January 23, 2025
​https://community.wolfram.com/groups/-/m/t/3363308