summaryrefslogtreecommitdiff
path: root/sys/src/libauthsrv/msqrt.mp
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-01-06 03:09:00 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2016-01-06 03:09:00 +0100
commit2dae1ed53a73d81bfb86778793a6bda265d5140d (patch)
treee037c4a663fc9d17906cc2045c488232ac223ece /sys/src/libauthsrv/msqrt.mp
parente064752dd476b7a2f76567f8cc15f9c2645e5d3d (diff)
auth: release dp9ik implementation and reentrant factotum
Diffstat (limited to 'sys/src/libauthsrv/msqrt.mp')
-rw-r--r--sys/src/libauthsrv/msqrt.mp100
1 files changed, 100 insertions, 0 deletions
diff --git a/sys/src/libauthsrv/msqrt.mp b/sys/src/libauthsrv/msqrt.mp
new file mode 100644
index 000000000..c34d5e480
--- /dev/null
+++ b/sys/src/libauthsrv/msqrt.mp
@@ -0,0 +1,100 @@
+# derived from: http://eli.thegreenplace.net/2009/03/07/computing-square-roots-in-python
+
+# Compute the Legendre symbol a|p using Euler's criterion.
+# p is a prime, a is relatively prime to p (if p divides a,
+# then a|p = 0)
+legendresymbol(a, p, r) {
+ pm1 = p-1;
+ mod(p) r = a^(pm1>>1);
+ if(r == pm1)
+ r = -1;
+}
+
+# Find a quadratic residue (mod p) of 'a'. p must be an
+# odd prime.
+#
+# Solve the congruence of the form:
+# x^2 = a (mod p)
+# And returns x. Node that p - x is also a root.
+#
+# 0 is returned if no square root exists for these
+# a and p.
+#
+# The Tonelli-Shanks algorithm is used (except
+# for some simple cases in which the solution is known
+# from an identity).
+msqrt(a, p, r) {
+ if(legendresymbol(a, p) != 1)
+ r = 0;
+ else if(a == 0)
+ r = 0;
+ else if(p == 2)
+ r = a;
+ else if(p%4 == 3){
+ e = p+1 >> 2;
+ mod(p) r = a^e;
+ } else {
+ # Partition p-1 to s * 2^e for an odd s (i.e.
+ # reduce all the powers of 2 from p-1)
+ s = p-1;
+ e = 0;
+ while(s%2 == 0){
+ s = s >> 1;
+ e = e + 1;
+ }
+
+ # Find some 'n' with a legendre symbol n|p = -1.
+ # Shouldn't take long.
+ n = 2;
+ while(legendresymbol(n, p) != -1)
+ n = n + 1;
+
+ # x is a guess of the square root that gets better
+ # with each iteration.
+ # b is the "fudge factor" - by now much we're off
+ # with the guess. The invariant x^2 == a*b (mod p)
+ # is maintained throughout the loop.
+ # g is used for successive powers of n to update
+ # both a and b
+ # e is the exponent - decreases with each update
+ mod(p){
+ x = a^(s+1 >> 1);
+ b = a^s;
+ g = n^s;
+ }
+ while(1==1){
+ t = b;
+ m = 0;
+ while(m < e){
+ if(t == 1)
+ break;
+ t = t*t % p;
+ m = m + 1;
+ }
+ if(m == 0){
+ r = x;
+ break;
+ }
+ t = 2^(e-m-1);
+ mod(p){
+ gs = g^t;
+ g = gs*gs;
+ x = x*gs;
+ b = b*g;
+ }
+ e = m;
+ }
+ }
+}
+
+# modular inverse square-root
+misqrt(a, p, r) {
+ if((p % 4) == 3){
+ e = ((p-3)>>2);
+ mod(p) r = a^e;
+ } else {
+ r = msqrt(a, p);
+ if(r != 0)
+ mod(p) r = 1/r;
+ }
+}