1+ /*
2+ * Extended Euclidean Algorithm
3+ * Input: a, b positive integers
4+ * Output: [s, t, d] where
5+ * as + bt = gcd(a, b) = d
6+ */
7+ function EEA ( a , b ) {
8+ if ( a > b )
9+ return _EEA ( a , b , 1 , 0 , 0 , 1 ) ;
10+ else
11+ return swapIndicies ( _EEA ( b , a , 1 , 0 , 0 , 1 ) , 0 , 1 ) ;
12+ }
13+
14+ /*
15+ * Helper function for EEA(). Assumes a > b
16+ */
17+ function _EEA ( a , b , s1 , s2 , t1 , t2 ) {
18+ const q = Math . floor ( a / b ) ;
19+ const r = a % b ;
20+ const s = s1 - s2 * q ;
21+ const t = t1 - t2 * q ;
22+
23+ // break condition for algorithm
24+ if ( r == 0 ) {
25+ return [ s2 , t2 , b ] ;
26+ }
27+ return _EEA ( b , r , s2 , s , t2 , t ) ;
28+ }
29+
30+ /*
31+ * Euclidean algorithm to find the gcd. Does not include s,t such that as + bt = gcd
32+ * Input: a, b positive integers
33+ * Output: gcd
34+ */
35+ function GCD ( a , b ) {
36+ if ( b > a )
37+ return _GCD ( b , a ) ;
38+ return _GCD ( a , b ) ;
39+ }
40+
41+ /*
42+ * Helper function for gcd. Assumes a > b
43+ */
44+ function _GCD ( a , b ) {
45+ const r = a % b ;
46+
47+ if ( r == 0 )
48+ return b ;
49+ return _GCD ( b , r ) ;
50+ }
51+
52+ /*
53+ * Returns true if input is prime, false otherwise
54+ * Input: integer
55+ * Output: [bool, factor]
56+ * - If num is prime: bool=true, factor=null
57+ * - If num is not prime: bool=false, factor='A x B'
58+ where num = AB
59+ */
60+ function isPrime ( num ) {
61+ if ( num == 1 )
62+ return [ false , '1 x 1' ]
63+
64+ // check for i = 2, ..., sqrt(num). If i divides num, then num is not prime
65+ for ( let i = 2 ; i <= Math . sqrt ( num ) ; i ++ ) {
66+ if ( num % i == 0 )
67+ return [ false , `${ num / i } x ${ i } ` ]
68+ }
69+ return [ true , null ]
70+ }
71+
72+ /*
73+ * Verify that the given key is a valid key mod phi_n. Returns true if key has multiplicative inverse
74+ * mod phi_n and that it is not it's own inverse (implies that it can work as a public key)
75+ * Note: - phi_n = (p - 1)(q - 1)
76+ - This function will never be called with invalid p,q
77+ * Input: key (int), phi_n (int)
78+ * Output: integer
79+ * -- null: error on my part, there is a bug somewhere
80+ * -- > 0: all good, key has a good multiplicative inverse mod phi_n [this is the inverse]
81+ * -- -1: bad, key is not invertible
82+ * -- -2: bad, key is it's own inverse mod phi_n
83+ */
84+ function verifyKey ( key ) {
85+ if ( p == null || q == null ) {
86+ console . error ( `ERROR: verifyKey(${ key } ): function was called when p,q were invalid.` ) ;
87+ return null ;
88+ }
89+
90+ const phi_n = ( p - 1 ) * ( q - 1 ) ;
91+ results = EEA ( key , phi_n ) ;
92+ inverse = results [ 0 ] ;
93+ gcd = results [ 2 ] ;
94+
95+ // doesn't have an inverse
96+ if ( gcd != 1 )
97+ return - 1 ;
98+ // is its own inverse
99+ else if ( key ** 2 % phi_n == 1 )
100+ return - 2 ;
101+
102+ // all good, return the inverse
103+ if ( inverse < 0 ) // don't return a negative number, this will be interpretted as an error
104+ inverse += phi_n ;
105+
106+ return inverse ;
107+ }
0 commit comments