├── manual.docx ├── manual.pdf ├── examples ├── FiniteFieldArithmeticI ├── pohlig_2_1_I ├── pohligI ├── ELGAMAL_EncryptionI ├── ECDSAI ├── ECarithmeticI ├── ELGAMAL_DSAI ├── pohlig.sh ├── ECDSA.sh ├── ECarithmetic.sh ├── ELGAMAL_DSA.sh ├── FiniteFieldArithmetic.sh ├── ELGAMAL_Encryption.sh ├── ECarithmetic_2_1_I ├── pohlig_2_2_I ├── command.sh ├── ECDSA.cpp ├── ELGAMAL_Encryption.cpp ├── ELGAMAL_DSA.cpp ├── pohlig.cpp ├── ECarithmetic_2_2_I ├── ECarithmetic.cpp └── FiniteFieldArithmetic.cpp ├── README.md ├── src ├── compile.sh ├── attacksECC.h ├── ellipticCurve.h ├── ECC.h ├── ECC.cpp ├── attacksECC.cpp └── ellipticCurve.cpp └── assets ├── givpoly1.h └── givpoly1io.inl /manual.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poojagarg/ECC/HEAD/manual.docx -------------------------------------------------------------------------------- /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poojagarg/ECC/HEAD/manual.pdf -------------------------------------------------------------------------------- /examples/FiniteFieldArithmeticI: -------------------------------------------------------------------------------- 1 | 7 2 | 2 3 | 2 4 | 1 5 | 6 6 | 3 7 | 0 8 | 4 9 | 1 10 | 2 11 | 6 12 | 11 13 | 14 | Prime p: 7 15 | positive integer m: 2 16 | if(m>1), irreducible polynomial of deg m: X^2+6*X+3 17 | element A- degree of A, followed by co-efficients: 4 18 | element B- degree of B, followed by co-efficients: 2*X+6 19 | Integer n(for scalar multiplication): 11 20 | -------------------------------------------------------------------------------- /examples/pohlig_2_1_I: -------------------------------------------------------------------------------- 1 | 2 2 | 4 3 | 4 4 | 1 5 | 0 6 | 0 7 | 1 8 | 1 9 | 3 10 | 1 11 | 0 12 | 0 13 | 0 14 | 3 15 | 1 16 | 0 17 | 0 18 | 1 19 | 1 20 | 1 21 | 1 22 | 1 23 | 0 24 | 3 25 | 1 26 | 1 27 | 1 28 | 1 29 | 3 30 | 1 31 | 1 32 | 1 33 | 1 34 | 3 35 | 1 36 | 0 37 | 1 38 | 1 39 | 22 40 | 41 | Prime p 42 | m 43 | if(m>1), give irreducible polynomial 44 | A 45 | B 46 | type of curve- 1 47 | degree d, Fp^(m*d) 48 | (x1,y1)=P 49 | (x2,y2)=Q 50 | n=Ord(P) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Elliptic Curve Cryptography 2 | Implementation in C++ 3 | 4 | Please refer to manual.pdf to use this implementation. 5 | 6 | This project implements the following-
7 | 1- Finite Field Arithmetic (of characteristic of Arbitrary precision)
8 | 2- Elliptic Curve Arithmetic
9 | 3- Attacks- Pollard Rho, Pohlig Hellman
10 | 4- Elliptic Curve Cryptosystems- Diffie-Hellman Key Exchange, Digital Signature Schemes (ECDSA, ELGAMAL), Public Key Encryption (ELGAMAL)
11 | -------------------------------------------------------------------------------- /examples/pohligI: -------------------------------------------------------------------------------- 1 | 7919 2 | 1 3 | 0 4 | 1001 5 | 0 6 | 75 7 | 0 8 | 1 9 | 0 10 | 4023 11 | 0 12 | 6036 13 | 0 14 | 4135 15 | 0 16 | 3169 17 | 7889 18 | 19 | Input 1 20 | _______ 21 | 22 | 599 23 | 1 24 | 0 25 | 0 26 | 0 27 | 1 28 | 0 29 | 1 30 | 0 31 | 60 32 | 0 33 | 19 34 | 0 35 | 277 36 | 0 37 | 239 38 | 600 39 | 40 | Input 2 41 | _________ 42 | 43 | Prime p 44 | m 45 | if(m>1), give irreducible polynomial 46 | A 47 | B 48 | type of curve= 0 49 | degree d= 1 so E(Fp^(m*d)) 50 | (x1,y1)=P 51 | (x2,y2)=Q 52 | n=Ord(P) -------------------------------------------------------------------------------- /examples/ELGAMAL_EncryptionI: -------------------------------------------------------------------------------- 1 | 7 2 | 2 3 | 2 4 | 1 5 | 6 6 | 3 7 | 1 8 | 2 9 | 3 10 | 1 11 | 5 12 | 4 13 | 0 14 | 1 15 | 0 16 | 2 17 | 1 18 | 2 19 | 3 20 | 1 21 | 3 22 | 5 23 | 1 24 | 6 25 | 2 26 | 59 27 | 28 | 29 | Prime p: 7 30 | positive integer m: 2 31 | if(m>1), irreducible polynomial of deg m: X^2+6*X+3 32 | element A- degree of A, followed by co-efficients: 2*X+3 33 | element B- degree of B, followed by co-efficients: 5*X+4 34 | type 0 35 | degree d: 1 36 | Base Point (x,y) (2,2*x+3) 37 | Message Point (x,y) (6*x+3,6*x+2) 38 | Integer n=Order(P): 59 39 | 40 | -------------------------------------------------------------------------------- /examples/ECDSAI: -------------------------------------------------------------------------------- 1 | 7 2 | 2 3 | 2 4 | 1 5 | 6 6 | 3 7 | 1 8 | 2 9 | 3 10 | 1 11 | 5 12 | 4 13 | 0 14 | 1 15 | 0 16 | 2 17 | 1 18 | 2 19 | 3 20 | 59 21 | 41 22 | 28 23 | 4 24 | 25 | Prime p: 7 26 | positive integer m: 2 27 | if(m>1), irreducible polynomial of deg m: X^2+6*X+3 28 | element A- degree of A, followed by co-efficients: 2*X+3 29 | element B- degree of B, followed by co-efficients: 5*X+4 30 | type 0 31 | degree d: 1 32 | Base Point (x,y) (2,2*x+3) 33 | Integer n=Order(P): 59 34 | Integer Message m, m1), irreducible polynomial of deg m: X^2+6*X+3 32 | element A- degree of A, followed by co-efficients: 2*X+3 33 | element B- degree of B, followed by co-efficients: 5*X+4 34 | type 0 35 | degree d: 1 36 | P (x1,y1): (2,2*X+3) 37 | Q (x2,y2): (1,6) 38 | T (x3,y3): (1,7) //not a point, you may check that (6*X+3,6*X+2) is a point -------------------------------------------------------------------------------- /examples/ELGAMAL_DSAI: -------------------------------------------------------------------------------- 1 | 7 2 | 2 3 | 2 4 | 1 5 | 6 6 | 3 7 | 1 8 | 2 9 | 3 10 | 1 11 | 5 12 | 4 13 | 0 14 | 1 15 | 0 16 | 2 17 | 1 18 | 2 19 | 3 20 | 59 21 | 41 22 | 17 23 | 0 24 | 4 25 | 1 26 | 4 27 | 4 28 | 29 | Prime p: 7 30 | positive integer m: 2 31 | if(m>1), irreducible polynomial of deg m: X^2+6*X+3 32 | element A- degree of A, followed by co-efficients: 2*X+3 33 | element B- degree of B, followed by co-efficients: 5*X+4 34 | type 0 35 | degree d: 1 36 | Base Point (x,y) (2,2*x+3) 37 | Integer n=Order(P): 59 38 | Integer Message m, m1), irreducible polynomial of deg m: x^4+x+1 48 | element A- degree of A, followed by co-efficients: x^3 49 | element B- degree of B, followed by co-efficients: x^3 + 1 50 | type 1, so no input for C 51 | degree d: 1 52 | P (x1,y1): (0010, 1111) which is (x,x^3+x^2+x+1) 53 | Q (x2,y2): (1100, 1100) 54 | T (x3,y3): (0001, 0010) //It is not a point, you may check that (0001, 0001) is a point -------------------------------------------------------------------------------- /examples/pohlig_2_2_I: -------------------------------------------------------------------------------- 1 | 2 2 | 7 3 | 7 4 | 1 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 1 11 | 1 12 | 5 13 | 1 14 | 0 15 | 0 16 | 0 17 | 1 18 | 0 19 | 5 20 | 1 21 | 0 22 | 0 23 | 0 24 | 1 25 | 1 26 | 2 27 | 2 28 | 1 29 | 0 30 | 1 31 | 1 32 | 2 33 | 1 34 | 0 35 | 0 36 | 3 37 | 1 38 | 1 39 | 0 40 | 1 41 | 5 42 | 1 43 | 1 44 | 1 45 | 1 46 | 0 47 | 1 48 | 5 49 | 1 50 | 0 51 | 1 52 | 0 53 | 0 54 | 1 55 | 145 56 | 57 | Prime p: 2 58 | positive integer m: 7 59 | if(m>1), irreducible polynomial of deg m: x^7+x+1 60 | element A- degree of A, followed by co-efficients: x^5+x 61 | element B- degree of B, followed by co-efficients: x^5+ x + 1 62 | type of curve- 2 63 | element C- degree of B, followed by co-efficients: x^2 + 1 64 | degree d: 1 65 | P (x1,y1): (100,1101) which is (x^2,x^3+x^2+1) 66 | Q (x2,y2): (111101, 101001) 67 | order(P)=145 -------------------------------------------------------------------------------- /examples/command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Run the following commands in the terminal with current directory as "examples" 3 | 4 | chmod +x *.sh 5 | 6 | ./FiniteFieldArithmetic.sh 7 | ./FiniteFieldArithmetic < FiniteFieldArithmeticI 8 | 9 | ./ECarithmetic.sh 10 | ./ECarithmetic < ECarithmeticI 11 | ./ECarithmetic < ECarithmetic_2_1_I 12 | ./ECarithmetic < ECarithmetic_2_2_I 13 | 14 | ./pohlig.sh 15 | ./pohlig < pohligI 16 | ./pohlig < pohlig_2_1_I 17 | ./pohlig < pohlig_2_2_I 18 | 19 | ./ELGAMAL_DSA.sh 20 | ./ELGAMAL_DSA < ELGAMAL_DSAI 21 | 22 | ./ECDSA.sh 23 | ./ECDSA < ECDSAI 24 | 25 | ./ELGAMAL_Encryption.sh 26 | ./ELGAMAL_Encryption < ELGAMAL_EncryptionI 27 | 28 | #To check examples program for Elliptic Curve of type 1 and type 2, we use input file that ends with _2_1_I and _2_2_I for type 1 and type 2 respectively. 29 | 30 | -------------------------------------------------------------------------------- /examples/ECDSA.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/ECC.h" 2 | 3 | using namespace Givaro; 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | SignatureECDSA S; 9 | Key K; 10 | ellipticCurveFq E_Fq;//define Elliptic Curve over Fq 11 | ExtensionField::Element x,y; 12 | std::cout<<"give (x,y) of Base Point: "; 13 | E_Fq.field->readElement(x); 14 | E_Fq.field->readElement(y); 15 | ecPoint basePoint(x,y); 16 | Integer n,message; 17 | cin>>n; 18 | cin>>message; 19 | 20 | KeyPairGeneration(K, basePoint,E_Fq,n);//ord(P)=n, generates (Q,d such that Q=d*P) 21 | SignatureGeneration(S, K,message,basePoint,E_Fq,n); 22 | showSignature(S); 23 | inputSignature(S); 24 | 25 | if(SignatureVerification(S,message,basePoint,K.Q,E_Fq,n)) 26 | { 27 | cout<<"Signature is valid"; 28 | } 29 | else 30 | { 31 | cout<<"Signature is invalid"; 32 | } 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /examples/ELGAMAL_Encryption.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/ECC.h" 2 | 3 | using namespace Givaro; 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | 9 | ecPoint M1, M2; 10 | Key K; 11 | ellipticCurveFq E_Fq;//define Elliptic Curve over Fq 12 | ExtensionField::Element x,y; 13 | std::cout<<"give (x,y) of Base Point: "; 14 | E_Fq.field->readElement(x); 15 | E_Fq.field->readElement(y); 16 | ecPoint basePoint(x,y); 17 | std::cout<<"give (x,y) of Message: "; 18 | E_Fq.field->readElement(x); 19 | E_Fq.field->readElement(y); 20 | ecPoint message(x,y); 21 | Integer n; 22 | cin>>n; 23 | KeyPairGeneration(K, basePoint,E_Fq,n);//ord(basePoint)=n, generates (Q,d such that Q=d*basePoint) 24 | EncryptionELGAMAL(M1,M2,basePoint,K.Q,E_Fq,n,message); 25 | DecryptionELGAMAL(message,K.d,basePoint,K.Q,E_Fq,n,M1,M2); 26 | E_Fq.show(message); 27 | return 0; 28 | } -------------------------------------------------------------------------------- /examples/ELGAMAL_DSA.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/ECC.h" 2 | 3 | using namespace Givaro; 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | SignatureELGAMAL S; 9 | Key K; 10 | ellipticCurveFq E_Fq;//define Elliptic Curve over Fq 11 | ExtensionField::Element x,y; 12 | std::cout<<"give (x,y) of Base Point: "; 13 | E_Fq.field->readElement(x); 14 | E_Fq.field->readElement(y); 15 | ecPoint basePoint(x,y); 16 | Integer n,message; 17 | cin>>n; 18 | cin>>message; 19 | 20 | KeyPairGeneration(K, basePoint,E_Fq,n);//ord(P)=n, generates (Q,d such that Q=d*P) 21 | SignatureGeneration(S, K,message,basePoint,E_Fq,n); 22 | showSignature(S,E_Fq); 23 | inputSignature(S,E_Fq); 24 | if(SignatureVerification(S,message,basePoint,K.Q,E_Fq,n)) 25 | { 26 | cout<<"Signature is valid"; 27 | } 28 | else 29 | { 30 | cout<<"Signature is invalid"; 31 | } 32 | return 0; 33 | } -------------------------------------------------------------------------------- /examples/pohlig.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/attacksECC.h" 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | //takes input parameter for E(Fq), where E is elliptic curve defined over K and Fq is extension of K 8 | ellipticCurveFq E_Fq; 9 | E_Fq.show(); 10 | Integer n,result; 11 | ExtensionField::Element x1,y1,x2,y2,x3,y3; 12 | std::cout<<"Write x1"; 13 | E_Fq.field->readElement(x1); 14 | std::cout<<"Write y1"; 15 | E_Fq.field->readElement(y1); 16 | std::cout<<"Write x2"; 17 | E_Fq.field->readElement(x2); 18 | std::cout<<"Write y2"; 19 | E_Fq.field->readElement(y2); 20 | ecPoint P(x1,y1); 21 | ecPoint Q(x2,y2); 22 | E_Fq.show(P); 23 | E_Fq.show(Q); 24 | std::cout<<"order of P?"; 25 | std::cin>>n; 26 | pohligHellman(result, P, Q,n,E_Fq); 27 | //if n is prime, can also use Pollard Rho method- pollardRho(result, P, Q,n,E_Fq); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /examples/ECarithmetic_2_2_I: -------------------------------------------------------------------------------- 1 | 2 2 | 7 3 | 7 4 | 1 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 1 11 | 1 12 | 2 13 | 1 14 | 1 15 | 0 16 | 5 17 | 1 18 | 0 19 | 0 20 | 0 21 | 1 22 | 1 23 | 2 24 | 1 25 | 1 26 | 1 27 | 1 28 | 5 29 | 1 30 | 0 31 | 0 32 | 0 33 | 1 34 | 1 35 | 5 36 | 1 37 | 0 38 | 0 39 | 1 40 | 0 41 | 0 42 | 5 43 | 1 44 | 0 45 | 1 46 | 1 47 | 0 48 | 0 49 | 5 50 | 1 51 | 1 52 | 1 53 | 0 54 | 1 55 | 0 56 | 3 57 | 1 58 | 0 59 | 1 60 | 1 61 | 6 62 | 1 63 | 1 64 | 1 65 | 0 66 | 1 67 | 1 68 | 1 69 | 70 | Prime p: 2 71 | positive integer m: 7 72 | if(m>1), irreducible polynomial of deg m: x^7+x+1 73 | element A- degree of A, followed by co-efficients: x^2+x 74 | element B- degree of B, followed by co-efficients: x^5+ x + 1 75 | type 2 76 | element C- degree of C, followed by co-efficients: x + 1 77 | degree d: 1 78 | P (x1,y1): (0100011, 0100100) which is (x^5+x+1, x^5+x^2) 79 | Q (x2,y2): (0101100, 0111010) 80 | T (x3,y3): (0001011, 1110111) //It is a point -------------------------------------------------------------------------------- /src/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | HOME=Users/poojagarg/Downloads/c_library/givaro-3.8.0 3 | g++ -w -DHAVE_CONFIG_H -I. -I/$HOME -I/$HOME -I/$HOME/src/kernel/system -I/$HOME/src/kernel/memory -I/$HOME/src/kernel/zpz -I/$HOME/src/kernel/integer -I/$HOME/src/kernel -I/$HOME/src/library/poly1 -I/$HOME/src/kernel/bstruct -I/$HOME/src/library/tools -O2 -Wall -g -DNDEBUG -UGIVARO_DEBUG -UDEBUG -std=gnu++11 -c -o ellipticCurve.o ellipticCurve.cpp 4 | g++ -w -DHAVE_CONFIG_H -I. -I/$HOME -I/$HOME -I/$HOME/src/kernel/system -I/$HOME/src/kernel/memory -I/$HOME/src/kernel/zpz -I/$HOME/src/kernel/integer -I/$HOME/src/kernel -I/$HOME/src/library/poly1 -I/$HOME/src/kernel/bstruct -I/$HOME/src/library/tools -O2 -Wall -g -DNDEBUG -UGIVARO_DEBUG -UDEBUG -std=gnu++11 -c -o ECC.o ECC.cpp 5 | g++ -w -DHAVE_CONFIG_H -I. -I/$HOME -I/$HOME -I/$HOME/src/kernel/system -I/$HOME/src/kernel/memory -I/$HOME/src/kernel/zpz -I/$HOME/src/kernel/integer -I/$HOME/src/kernel -I/$HOME/src/library/poly1 -I/$HOME/src/kernel/bstruct -I/$HOME/src/library/tools -O2 -Wall -g -DNDEBUG -UGIVARO_DEBUG -UDEBUG -std=gnu++11 -c -o attacksECC.o attacksECC.cpp 6 | 7 | -------------------------------------------------------------------------------- /src/attacksECC.h: -------------------------------------------------------------------------------- 1 | #ifndef EC_H 2 | #define EC_H 3 | #include "ellipticCurve.h" 4 | #endif 5 | 6 | #ifndef EC_GIVAROINTEGER_H 7 | #define EC_GIVAROINTEGER_H 8 | #include "gmp++/gmp++.h" 9 | #include 10 | #include 11 | #include 12 | #endif 13 | 14 | using namespace Givaro; 15 | 16 | /*computes result such that Q=result*P. 17 | Assumption n is prime, n=order(P) in E(Fq) represented by E_Fq, L is number of partition functions*/ 18 | void pollardRho(Integer& result, ecPoint& P, ecPoint& Q,Integer n,ellipticCurveFq& E_Fq,int L); 19 | /*computes result such that Q=result*P. 20 | n=order(P) in E(Fq) represented by E_Fq. 21 | It uses function pollardRho to compute each smaller instance of ECDLP*/ 22 | void pohligHellman(Integer& result, ecPoint& P, ecPoint& Q,Integer n,ellipticCurveFq& E_Fq); 23 | 24 | /*Auxillary Functions*/ 25 | 26 | /*result=H(input) where 0=& a,std::vector& p); 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/ECarithmetic.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/ellipticCurve.h" 2 | 3 | using namespace Givaro; 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | ellipticCurveFq E_Fq; 9 | E_Fq.show(); 10 | ExtensionField::Element x1,y1,x2,y2,x3,y3; 11 | cout<<"Write x1: "; 12 | E_Fq.field->readElement(x1,true); 13 | cout<<"Write y1: "; 14 | E_Fq.field->readElement(y1,true); 15 | cout<<"Write x2: "; 16 | E_Fq.field->readElement(x2,true); 17 | cout<<"Write y2: "; 18 | E_Fq.field->readElement(y2,true); 19 | ecPoint P(x1,y1); 20 | ecPoint Q(x2,y2); 21 | ecPoint R; 22 | E_Fq.Double(R,P);//R=2*P 23 | cout<readElement(x3, true); 31 | E_Fq.field->readElement(y3, true); 32 | ecPoint T(x3,y3); 33 | if(E_Fq.verifyPoint(T)) 34 | { 35 | cout<<"T is a point."; 36 | } 37 | else 38 | { 39 | cout<<"T is not a point."; 40 | } 41 | cout<: 29 | // -- 30 | // ========================================================================== 31 | template class Poly1Dom; 32 | 33 | template class Poly1Dom; 34 | template class Poly1Dom; 35 | 36 | } // Givaro 37 | 38 | #include "givaro/givpoly1dense.h" 39 | // #include "givaro/givvectorsparse.h" 40 | // -- should be included in specialized class #include "givaro/givvectops.inl" 41 | #include "givaro/givpoly1denseops.inl" 42 | // #include "givaro/givvectsparseops.inl" 43 | 44 | #endif // __GIVARO_poly1_H 45 | -------------------------------------------------------------------------------- /examples/FiniteFieldArithmetic.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/ellipticCurve.h" 2 | 3 | using namespace Givaro; 4 | 5 | int main() 6 | { 7 | int p,m; 8 | std::cin>>p>>m; 9 | ExtensionField E(p, m); 10 | typedef ExtensionField::Element e;//polynomial element 11 | e A,B,R; 12 | std::cout<<"1-Add, 2-Sub, 3-Mul, 4-Div, 5-Inv, 6-Neg, 7-Sqr, 8-Scalar multiply"; 13 | 14 | std::cout<<"Write A"; 15 | E.readElement(A,true); 16 | std::cout<<"Write B"; 17 | E.readElement(B,true); 18 | Integer n; 19 | std::cin>>n; 20 | switch(1) 21 | { 22 | case 1: 23 | E.add(R,A,B); 24 | E.writeElement(A); 25 | std::cout<<" + "; 26 | E.writeElement(B); 27 | std::cout<<"="; 28 | E.writeElement(R); 29 | std::cout<::read: syntax error no '('")); 28 | #endif 29 | 30 | _domain.read(sin); 31 | 32 | sin >> std::ws >> ch; 33 | #ifdef GIVARO_DEBUG 34 | if (ch != ',') 35 | GivError::throw_error( 36 | GivBadFormat("Poly1Dom::read: syntax error no ','")); 37 | #endif 38 | 39 | sin >> _x; 40 | 41 | sin >> std::ws >> ch; 42 | #ifdef GIVARO_DEBUG 43 | if (ch != ')') 44 | GivError::throw_error( 45 | GivBadFormat("Poly1Dom::read: syntax error no ')'")); 46 | #endif 47 | return sin; 48 | } 49 | 50 | template 51 | std::ostream& Poly1Dom::write( std::ostream& o ) const 52 | { 53 | return _domain.write(o) << '[' << _x << ']'; 54 | } 55 | 56 | 57 | 58 | template 59 | std::ostream& Poly1Dom::write( std::ostream& o, const Rep& R) const 60 | { 61 | if (R.size()) { 62 | Rep P; assign(P, R); 63 | setdegree(P); 64 | if (P.size()) { 65 | if (! _domain.isZero(P[0])) { 66 | if (_domain.isOne(P[0])) 67 | _domain.write(o,P[0]); 68 | else 69 | _domain.write(o << "(",P[0]) << ")"; 70 | } 71 | if (P.size() > 1) { 72 | if (! _domain.isZero(P[0])) o << " + "; 73 | if (! _domain.isZero(P[1])) { 74 | if (! _domain.isOne(P[1])) { 75 | _domain.write(o << "(",P[1]) << ")*"; 76 | } 77 | o << _x; 78 | } 79 | for(unsigned long l=2;l 96 | std::istream& Poly1Dom::read ( std::istream& i, Rep& P) const 97 | { 98 | long deg; 99 | i >> deg; 100 | init(P,Degree(deg)); 101 | // JGD 18.09.2002 102 | for(;deg>=0;--deg) 103 | _domain.read( i, P[(size_t)deg]); 104 | // i >> P[deg]; 105 | return i; 106 | } 107 | template 108 | std::istream& Poly1Dom::read ( std::istream& i, Rep& P, bool flag) const //Pooja for easy input 109 | { 110 | if(flag) 111 | return Poly1Dom::read(i,P); 112 | long deg; 113 | i >> deg; 114 | init(P,Degree(deg)); 115 | // JGD 18.09.2002 116 | long index; 117 | i>>index; 118 | while(index>-1&&index<=deg) 119 | { 120 | _domain.read( i, P[(size_t)index]); 121 | i>>index; 122 | } 123 | 124 | return i; 125 | } 126 | } // Givaro 127 | #endif // __GIVARO_poly1_io_INL 128 | -------------------------------------------------------------------------------- /src/ellipticCurve.h: -------------------------------------------------------------------------------- 1 | /* 2 | check if "=="" operator for type Element in ecPoint is defined 3 | */ 4 | #ifndef GIVARO_ZPZ_H 5 | #define GIVARO_ZPZ_H 6 | #include 7 | #include 8 | #endif 9 | 10 | #include 11 | 12 | using namespace Givaro; 13 | 14 | 15 | class ExtensionField 16 | { 17 | public: 18 | Integer p,m; 19 | typedef ZpzDom primeField; 20 | typedef Poly1Dom< primeField, Dense >::Element Element; 21 | primeField Fp; 22 | // Fp[X]- Polynomials over Fp, with X as indeterminate 23 | Poly1Dom< primeField, Dense > Fp_X; 24 | //irred is an irreducible polynomial of degree m in Fp_X 25 | Element irred,zero,one,mOne; 26 | 27 | ExtensionField(Integer p, Integer m); 28 | 29 | ExtensionField operator=(const ExtensionField& E); 30 | //Return R=(A+B)%p 31 | Element& add(Element& R, const Element& A, const Element& B) const; 32 | Element& addin(Element& R, const Element& A) const; 33 | //Return R=(A-B)%p 34 | Element& sub(Element& R, const Element& A, const Element& B) const; 35 | //Return R=-B 36 | Element& neg(Element& R, const Element& A) const; 37 | //Return R=A*B%irred 38 | Element& mul(Element& R, const Element& A, const Element& B) const; 39 | //Return R=A*A%irred 40 | Element& sqr(Element& R, const Element& A) const; 41 | //Return inverse of (A) with irred polynomial, if gcd(A,irred)!=1, then it return 0 42 | Element& inv(Element& I, const Element& A) const; 43 | //I+A=0 44 | Element& additiveInv(Element& I, const Element& A) const; 45 | //Return Q, such that Q=A/B=A*(inverse of B), 46 | Element& div(Element& Q, const Element& A, const Element& B) const; 47 | //R=k*A; 48 | Element& scalarMultiply(Element& R,const Element& A,Integer k) const; 49 | 50 | void readElement(Element& A, bool flag=true); 51 | void writeElement(Element& A); 52 | 53 | bool isElement(const Element& A); 54 | }; 55 | class ecPoint 56 | { 57 | public: 58 | typedef ExtensionField::Element Element; 59 | ecPoint() : identity(true) {} 60 | ecPoint(bool b); 61 | ecPoint(Element x1, Element y1); 62 | ecPoint operator=( const ecPoint& P); 63 | bool operator==(const ecPoint& t) const; 64 | bool operator< (const ecPoint& t) const; 65 | 66 | bool identity; 67 | Element x, y; 68 | }; 69 | 70 | /* 71 | Elliptic Curve over field p^m, defined by co-efficient a,b,c (3 possible equations) 72 | type 0: E/K, char(K)!=2: y2 = x3+ax+b, 73 | type 1: non-supersingular E/F2m: y2 + xy = x3+ax2+b, 74 | tyep 2: supersingular E/F2m: y2 + cy = x3 + ax + b 75 | */ 76 | 77 | class ellipticCurve 78 | { 79 | public: 80 | 81 | typedef ExtensionField::Element Element;//element over the field 82 | ExtensionField* Kptr; //elliptic curve over field K 83 | Element A,B,C; //equation of curve, depending upon the char(K) 84 | 85 | ellipticCurve(); 86 | ~ellipticCurve(); 87 | 88 | ellipticCurve operator=( const ellipticCurve& F); 89 | void print(); 90 | int type; //0,1,2 91 | }; 92 | 93 | class ellipticCurveFq 94 | { 95 | public: 96 | ellipticCurve* ec; 97 | int d; //elliptic curve ec/Fq, abelian group of points E(Fq^d), default d=1 98 | typedef ExtensionField::Element fieldElement; 99 | typedef ecPoint Point; 100 | ExtensionField* field;//coordinates of point belong to this field F(q^d) 101 | //hence arithmetic on co-ordinates is done in this field 102 | Point identity; 103 | ellipticCurveFq(); 104 | ellipticCurveFq(ellipticCurve* e); 105 | ~ellipticCurveFq(); 106 | //Q=-P 107 | const Point& inv(Point& Q, const Point &P); 108 | //is Q=-P? 109 | bool isInv(const Point& Q, const Point &P); 110 | //R=2*P 111 | Point& Double(Point &R,Point &P); 112 | //R=P+Q 113 | Point& add(Point &R,Point &P, Point &Q); 114 | //R=k*P 115 | Point& scalarMultiply(Point&R, Point& P, Integer k, Integer order);//order of P 116 | //R=a*P+b*Q 117 | void compute(ecPoint& R,Integer a, ecPoint& P,Integer b,ecPoint& Q,Integer n);//ord(P)=n 118 | bool verifyPoint(const Point &P) const; 119 | void show(Point& P); 120 | void show(); 121 | 122 | }; -------------------------------------------------------------------------------- /src/ECC.h: -------------------------------------------------------------------------------- 1 | #ifndef EC_H 2 | #define EC_H 3 | #include "ellipticCurve.h" 4 | #endif 5 | 6 | class Key 7 | { 8 | public: 9 | ecPoint Q; 10 | Integer d;//Q=dP 11 | }; 12 | class publicKey 13 | { 14 | public: 15 | ellipticCurveFq* E_Fq_ptr; 16 | ecPoint* basePoint_ptr; 17 | Integer n; //order of basePoint 18 | ecPoint* Q_ptr; //Q=d*P, where d is private 19 | }; 20 | class SignatureECDSA 21 | { 22 | public: 23 | Integer r,s; 24 | }; 25 | class SignatureELGAMAL 26 | { 27 | public: 28 | Integer s; 29 | ecPoint R; 30 | }; 31 | /*Input: R is x-coordinate of point in E(Fq) represented by E_Fq and mod = Order(basepoint) 32 | Output: Computes result=f(R), 0<=result*/ 47 | bool publicKeyValidation(ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n); 48 | 49 | /*ECDSA Signature Generation 50 | Input: Secret Key K, message m to be signed, basepoint P in E(Fq) represented by E_Fq, n=order(P) 51 | Output: Signature S for the message*/ 52 | void SignatureGeneration(SignatureECDSA& S, Key& K,Integer& message,ecPoint& P,ellipticCurveFq& E_Fq,Integer& n); 53 | 54 | /*ECDSA Signature Verification 55 | Input: Signature S for the message m, Secret Key K, basepoint P in E(Fq) represented by E_Fq, n=order(P), Q=d*P where d is private key 56 | Output: returns true if message is signed*/ 57 | bool SignatureVerification(SignatureECDSA& S,Integer& message,ecPoint& P,ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n); 58 | 59 | /*ELGAMAL Signature Generation 60 | Input: Secret Key K, message m to be signed, basepoint P in E(Fq) represented by E_Fq, n=order(P) 61 | Output: Signature S for the message*/ 62 | void SignatureGeneration(SignatureELGAMAL& S, Key& K,Integer& message,ecPoint& P,ellipticCurveFq& E_Fq,Integer& n); 63 | 64 | /*ELGAMAL Signature Verification 65 | Input: Signature S for the message m, Secret Key K, basepoint P in E(Fq) represented by E_Fq, n=order(P), Q=d*P where d is private key 66 | Output: returns true if message is signed*/ 67 | bool SignatureVerification(SignatureELGAMAL& S,Integer& message,ecPoint& P,ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n); 68 | 69 | /*prints Signature of a message m(an Ineger) generated by ECDSA*/ 70 | void showSignature(SignatureECDSA& S); 71 | 72 | /*prints Signature of a message m(an Ineger) generated by ELGAMAL*/ 73 | void showSignature(SignatureELGAMAL& S,ellipticCurveFq& E_Fq); 74 | 75 | /*To input ELGAMAL Signature S as told by the signee of message*/ 76 | void inputSignature(SignatureELGAMAL& S,ellipticCurveFq& E_Fq); 77 | 78 | /*To input ECDSA Signature S as told by the signee of message*/ 79 | void inputSignature(SignatureECDSA& S); 80 | 81 | /*Input: basepoint P in E(Fq) represented by E_Fq, n=order(P) 82 | Output: Ka- public Key with Alice, Kb- public Key with Bob 83 | a and b: secret integer by Alice and Bob respectively*/ 84 | void DiffieHellmanKeyExchange(Integer& a, Integer& b, ecPoint& Ka,ecPoint& Kb,ecPoint& P,ellipticCurveFq& E_Fq,Integer& n); 85 | 86 | /*Input: message m and E(Fq) 87 | Output: Point representation of m as M ∈ E(Fq) 88 | This function is not yet defined*/ 89 | void integerToPoint(ecPoint& M,Integer& m, ellipticCurveFq& E_Fq); 90 | 91 | /*Input: message represented as a Point in E(Fq), basepoint P in E(Fq) represented by E_Fq, n=order(P) 92 | Output: Encrypted message {M1,M2} */ 93 | void EncryptionELGAMAL(ecPoint& M1, ecPoint& M2, ecPoint& P,ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n, ecPoint& message); 94 | 95 | /*Input: Encrypted message {M1,M2}, basepoint P in E(Fq) represented by E_Fq, n=order(P) 96 | Output: message represented as a Point in E(Fq)*/ 97 | void DecryptionELGAMAL(ecPoint& message, Integer& d, ecPoint& P,ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n, ecPoint& M1, ecPoint& M2); 98 | -------------------------------------------------------------------------------- /src/ECC.cpp: -------------------------------------------------------------------------------- 1 | #include "ECC.h" 2 | 3 | using namespace std; 4 | 5 | //Algorithm 4.24 Key pair generation 6 | void convertElementToInt(Integer& result,ExtensionField::Element& R, Integer& mod, ellipticCurveFq& E_Fq) 7 | { 8 | result=0; 9 | ExtensionField::Element P; 10 | if (R.size()) 11 | { 12 | E_Fq.field->Fp_X.assign(P, R); 13 | E_Fq.field->Fp_X.setdegree(P); 14 | for(unsigned long l=0;l, ord(P)=n, 37 | { 38 | if(Q.identity) 39 | return false; 40 | if(!(E_Fq.field->isElement(Q.x)&&E_Fq.field->isElement(Q.y))) 41 | return false; 42 | if(!E_Fq.verifyPoint(Q)) 43 | return false; 44 | ecPoint T; 45 | E_Fq.scalarMultiply(T,Q,n,n); 46 | if(!T.identity) 47 | return false; 48 | return true; 49 | } 50 | 51 | /*Algorithm 4.29 ECDSA signature generation*/ 52 | //Assumption: H(x) gives a number of bitlength <= n 53 | void SignatureGeneration(SignatureECDSA& S, Key& K,Integer& message,ecPoint& P,ellipticCurveFq& E_Fq,Integer& n) 54 | { 55 | Integer k,_x=1,e; 56 | ecPoint temp; 57 | do 58 | { 59 | do 60 | { 61 | Integer::random_lessthan (k,n); 62 | E_Fq.scalarMultiply(temp,P,k,n); 63 | convertElementToInt(_x,temp.x,n,E_Fq); 64 | S.r=_x%n; 65 | }while(S.r==0); 66 | e=H(message,n); 67 | invin(k,n); 68 | S.s=((e+K.d*S.r)*k)%n; 69 | }while(S.s==0); 70 | } 71 | /*Algorithm 4.30 ECDSA signature verification*/ 72 | bool SignatureVerification(SignatureECDSA& S,Integer& message,ecPoint& P,ecPoint& Q,ellipticCurveFq& E_Fq,Integer& n) 73 | { 74 | if(S.r>n-1||S.r<1||S.s>n-1||S.s<1) 75 | return false; 76 | Integer e,w,u1,u2; 77 | ecPoint X; 78 | e=H(message,n); 79 | inv(w,S.s,n); 80 | u1=(e*w)%n; 81 | u2=(S.r*w)%n; 82 | E_Fq.compute(X,u1,P,u2,Q,n); 83 | if(X.identity) 84 | return false; 85 | convertElementToInt(e,X.x,n,E_Fq); 86 | w=e%n; 87 | if(w==S.r) 88 | return true; 89 | return false; 90 | } 91 | //Assumption: m>S.s; 155 | std::cout<<"give (x,y) of Point R in Signature: "; 156 | E_Fq.field->readElement(S.R.x); 157 | E_Fq.field->readElement(S.R.y); 158 | } 159 | void inputSignature(SignatureECDSA& S) 160 | { 161 | cin>>S.s>>S.r; 162 | } 163 | void showSignature(SignatureECDSA& S) 164 | { 165 | cout<<"s: "<field.p, E_Fq->field.m); 178 | E_Fq->field.Fp_X.assign(acc,Fp_X.zero); 179 | (); 180 | 181 | integerToElement(messageE,message,E_Fq->field); 182 | for(int j=0;j<100;j++) 183 | { 184 | E_Fq->field.scalarMultiply(temp,messageE,(Integer)100); 185 | E_Fq->field.add(Xj,temp,acc); 186 | compute(); 187 | } 188 | 189 | }*/ -------------------------------------------------------------------------------- /src/attacksECC.cpp: -------------------------------------------------------------------------------- 1 | /*INPUT: P ∈ E(Fq) of prime order n, Q ∈ ⟨P⟩. 2 | OUTPUT: The discrete logarithm l = logP Q.*/ 3 | 4 | #include "attacksECC.h" 5 | 6 | using namespace Givaro; 7 | using namespace std; 8 | 9 | #define NumberOfPartitions_Pollard 16 10 | #define pollardThreshold 10 //Pollard rho would try 10 times 11 | #define noMatchThreshold 50 12 | 13 | Integer& H(Integer& result,ecPoint& input, int L, ellipticCurveFq& E_Fq) 14 | { 15 | Integer mod=(Integer)L; 16 | //Integer::random_lessthan (result,mod); 17 | ExtensionField::Element P,R=input.x,Q=input.y; 18 | if (R.size()) 19 | { 20 | E_Fq.field->Fp_X.assign(P, R); 21 | E_Fq.field->Fp_X.setdegree(P); 22 | for(unsigned long l=0;lFp_X.assign(P, Q); 31 | E_Fq.field->Fp_X.setdegree(P); 32 | for(unsigned long l=0;l>L; 63 | } 64 | Integer a[L],b[L]; 65 | Integer c1,c2,d1,d2; 66 | //a=(Integer*)malloc(sizeof(Integer)*L); 67 | //b=(Integer*)malloc(sizeof(Integer)*L); 68 | 69 | ecPoint R[L],P1,P2,tP; 70 | Integer::seeding(); 71 | 72 | for(int i=0; ipollardThreshold) 82 | { 83 | cout<<"pollard rho method failed to compute, try giving your own initial number c1 and d1"<noMatchThreshold) 113 | { 114 | cout<<"pollard rho method failed to compute, try changing partition function"<& a,std::vector& p) 151 | { 152 | Integer length=p.size(); 153 | Integer n=1; 154 | for(Integer i=0;i m(length),c(length); 157 | for(Integer i=0;i IP; 169 | 170 | std::vector Lf; 171 | std::vector Le; 172 | IP.set(Lf,Le,n,0); 173 | Integer length=Lf.size(); 174 | cout< res(length); 176 | ecPoint P0,_Q,temp1,temp2,S; 177 | Integer z, power,f; 178 | for(Integer i=0;ip=p; 12 | this->m=m; 13 | Fp=primeField((primeField::Residu_t)p); 14 | Fp_X=Poly1Dom< primeField, Dense >( Fp, Indeter("X") ); 15 | if(m==1) 16 | Fp_X.assign(irred,(Element)p); 17 | else 18 | { 19 | 20 | cout<<"Give an irreducible polynomial of degree "<1) 70 | { 71 | Element tmp,Q; 72 | Fp_X.mul(tmp,A,B); 73 | Fp_X.divmod(Q,R,tmp,irred); 74 | } 75 | else 76 | Fp_X.mul(R,A,B); 77 | return R; 78 | } 79 | //Return R=A*A%irred 80 | ExtensionField::Element& ExtensionField::sqr(Element& R, const Element& A) const 81 | { 82 | if(m>1) 83 | { 84 | Element tmp,Q; 85 | Fp_X.sqr(tmp,A); 86 | Fp_X.divmod(Q,R,tmp,irred); 87 | } 88 | else 89 | Fp_X.sqr(R,A); 90 | return R; 91 | } 92 | //Return inverse of (A) with irred polynomial, if gcd(A,irred)!=1, then it return 0 93 | ExtensionField::Element& ExtensionField::inv(Element& I, const Element& A) const 94 | { 95 | Element tmp,D; 96 | D=Fp_X.gcd(D,I,tmp,A,irred); 97 | if(Fp_X.isOne(D)) 98 | return I; 99 | Fp_X.assign(I,Fp_X.zero); 100 | return I; 101 | 102 | } 103 | ExtensionField::Element& ExtensionField::additiveInv(Element& I, const Element& A) const 104 | { 105 | Fp_X.sub(I,Fp_X.zero,A); 106 | return I; 107 | 108 | } 109 | 110 | //Return Q, such that Q=A/B=A*(inverse of B), 111 | ExtensionField::Element& ExtensionField::div(Element& Q, const Element& A, const Element& B) const 112 | { 113 | Element I; 114 | I=inv(I,B); 115 | mul(Q,A,I); 116 | return Q; 117 | } 118 | ExtensionField::Element& ExtensionField::scalarMultiply(Element& R,const Element& A,Integer k) const 119 | { 120 | k=k%p; 121 | if(m==1) 122 | { 123 | Element eK; 124 | primeField::Element tmp; 125 | Fp_X.assign(eK,Fp.init(tmp,k)); 126 | Fp_X.mul(R,A,eK); 127 | return R; 128 | } 129 | Element tmp,acc=A; 130 | Fp_X.assign(R,zero); 131 | while(k>0) 132 | { 133 | if(k%2) 134 | Fp_X.addin(R,acc); 135 | acc=Fp_X.add(tmp,acc,acc); //acc=tmp=2*acc 136 | k=k/2; 137 | } 138 | return R; 139 | } 140 | void ExtensionField::readElement(Element& P, bool flag) 141 | { 142 | Fp_X.read(cin,P,flag); 143 | } 144 | void ExtensionField::writeElement(Element& A) 145 | { 146 | cout<<"( "; 147 | Fp_X.write(cout<<"",A); 148 | cout<<" )"; 149 | } 150 | bool ExtensionField::isElement(const Element& A) 151 | { 152 | Degree d=Fp_X.degree(A); 153 | if(d._degidentity=true; 172 | return *this; 173 | } 174 | 175 | this->identity=P.identity; 176 | this->x=P.x; 177 | this->y=P.y; 178 | return *this; 179 | } 180 | bool ecPoint::operator==(const ecPoint& t) const 181 | {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);} 182 | bool ecPoint::operator< (const ecPoint& t) const 183 | {return identity ? !t.identity : (!t.identity && (x>p>>m; 191 | Kptr=new ExtensionField(p,m); 192 | cout<<"Write A: "; 193 | Kptr->readElement( A); 194 | cout<<"Write B: "; 195 | Kptr->readElement( B); 196 | cout<<"type? "; 197 | cin>>type; 198 | if(type==2) 199 | { 200 | cout<<"Write C: "; 201 | Kptr->readElement( C); 202 | } 203 | cout<writeElement(A); 224 | cout<writeElement(B); 227 | cout<writeElement(C); 230 | cout<>d; 239 | if(d!=1) 240 | field=new ExtensionField(ec->Kptr->p,(ec->Kptr->m)*d); 241 | else 242 | field=ec->Kptr; 243 | identity.identity=true; 244 | this->d=d; 245 | } 246 | ellipticCurveFq::ellipticCurveFq(ellipticCurve* e) 247 | { 248 | ec=e; 249 | cout<<"degree d? "; 250 | cin>>d; 251 | if(d!=1) 252 | field=new ExtensionField(ec->Kptr->p,(ec->Kptr->m)*d); 253 | else 254 | field=ec->Kptr; 255 | identity.identity=true; 256 | this->d=d; 257 | } 258 | ellipticCurveFq::~ellipticCurveFq() 259 | { 260 | free(ec); 261 | free(field); 262 | } 263 | const ellipticCurveFq::Point& ellipticCurveFq::inv(Point& Q, const Point &P) 264 | { 265 | if(P.identity) 266 | { 267 | Q.identity=true; 268 | return Q; 269 | } 270 | Q.identity=false; 271 | Point T; 272 | switch(ec->type) 273 | { 274 | case 0: 275 | Q.x=P.x; 276 | field->additiveInv(Q.y,P.y); //Q.y+P.y=0 277 | return Q; 278 | 279 | case 1: 280 | Q.x=P.x; 281 | field->add(Q.y,P.y,P.x); 282 | //Q.y+=Q.x; 283 | return Q; 284 | 285 | case 2: 286 | Q.x=P.x; 287 | field->add(Q.y,P.y,ec->C); 288 | 289 | //Q.y+=ec->C; 290 | return Q; 291 | default: 292 | return Q; 293 | 294 | } 295 | } 296 | bool ellipticCurveFq::isInv(const Point& Q, const Point &P) //is Q+P=point at inifinity? 297 | { 298 | Point R; 299 | inv(R,P); 300 | //cout<<"At inverse check"; show(R); 301 | if(R==Q) 302 | return true; 303 | return false; 304 | } 305 | 306 | ellipticCurveFq::Point& ellipticCurveFq::Double(Point &R,Point &P) 307 | { 308 | if (P.identity||isInv(P,P)) 309 | { 310 | R.identity=true; 311 | return R; 312 | } 313 | 314 | R.identity=false; 315 | fieldElement x,y,x12; 316 | fieldElement slopeSquare, slope; 317 | field->sqr(x12,P.x); 318 | fieldElement _3x12,_2y,_3x12pA,_2x,_x,slope_x; 319 | fieldElement xpy,Bdx12,slopex,slopex_x; 320 | fieldElement x12pA,ypC,xpx,slopexpx; 321 | switch(ec->type) 322 | { 323 | case 0: 324 | 325 | field->scalarMultiply(_3x12,x12,3); 326 | field->scalarMultiply(_2y,P.y,2); 327 | field->add(_3x12pA,_3x12,ec->A); 328 | field->div(slope,_3x12pA,_2y); 329 | field->sqr(slopeSquare,slope); 330 | field->scalarMultiply(_2x,P.x,2); 331 | field->sub(x,slopeSquare,_2x); 332 | field->sub(_x,P.x,x); 333 | field->sub(y,field->mul(slope_x,slope,_x),P.y); 334 | 335 | R.x=x; 336 | R.y=y; 337 | return R; 338 | 339 | case 1: 340 | 341 | field->add(xpy,x12,P.y); 342 | field->div(slope,xpy,P.x); 343 | field->div(Bdx12,ec->B,x12); 344 | field->add(x,x12,Bdx12); 345 | field->mul(slopex,slope,x); 346 | field->add(slopex_x,slopex,x); 347 | field->add(y,x12,slopex_x); 348 | R.x=x; 349 | R.y=y; 350 | return R; 351 | case 2: 352 | 353 | field->add(x12pA,x12,ec->A); 354 | field->div(slope,x12pA,ec->C); 355 | field->sqr(slopeSquare,slope); 356 | x=slopeSquare; 357 | field->add(ypC,P.y,ec->C); 358 | field->add(xpx,P.x,x); 359 | field->mul(slopexpx,xpx,slope); 360 | field->add(y,ypC,slopexpx); 361 | R.x=x; 362 | R.y=y; 363 | return R; 364 | } 365 | return R; 366 | } 367 | ellipticCurveFq::Point& ellipticCurveFq::add(Point &R,Point &P, Point &Q) 368 | { 369 | if(P.identity&&Q.identity||isInv(P,Q)) 370 | { 371 | R.identity=true; 372 | return R; 373 | } 374 | R.identity=false; 375 | if (P.identity) 376 | { 377 | R.x=Q.x; 378 | R.y=Q.y; 379 | return R; 380 | } 381 | if (Q.identity) 382 | { 383 | R.x=P.x; 384 | R.y=P.y; 385 | return R; 386 | } 387 | if(P==Q) 388 | return Double(R,P); 389 | 390 | fieldElement x,y,x12; 391 | fieldElement slopeSquare, slope; 392 | fieldElement y2m1,x2m1,x1p2,x1m3,slopex1m3,y1pC,x1p2pA,x1p2pApS,slopex1m3px3; 393 | field->sub(y2m1,Q.y,P.y); 394 | field->sub(x2m1,Q.x,P.x); 395 | field->div(slope,y2m1,x2m1); 396 | field->sqr(slopeSquare,slope); 397 | field->add(x1p2,P.x,Q.x); 398 | switch(ec->type) 399 | { 400 | case 0: 401 | field->sub(x,slopeSquare,x1p2); 402 | field->sub(x1m3,P.x,x); 403 | field->mul(slopex1m3,slope,x1m3); 404 | field->sub(y,slopex1m3,P.y); 405 | R.x=x; 406 | R.y=y; 407 | return R; 408 | case 1: 409 | field->add(x1p2pA,x1p2,ec->A); 410 | field->add(x1p2pApS,x1p2pA,slope); 411 | field->add(x,x1p2pApS,slopeSquare); 412 | field->add(x1m3,P.x,x); 413 | field->mul(slopex1m3,slope,x1m3); 414 | field->add(slopex1m3px3,slopex1m3,x); 415 | field->add(y,slopex1m3px3,P.y); 416 | R.x=x; 417 | R.y=y; 418 | return R; 419 | case 2: 420 | field->add(x,slopeSquare,x1p2); 421 | field->add(x1m3,P.x,x); 422 | field->mul(slopex1m3,slope,x1m3); 423 | field->add(y1pC,P.y,ec->C); 424 | field->add(y,y1pC,slopex1m3); 425 | R.x=x; 426 | R.y=y; 427 | return R; 428 | } 429 | return R; 430 | } 431 | void ellipticCurveFq::show(Point& P) 432 | { 433 | if(P.identity) 434 | { 435 | cout<<"o"; 436 | return; 437 | } 438 | 439 | cout<<"("; 440 | field->writeElement(P.x); 441 | cout<<", "; 442 | field->writeElement(P.y); 443 | cout<<")"; 444 | } 445 | //R=kP 446 | ellipticCurveFq::Point& ellipticCurveFq::scalarMultiply(Point&R, Point& P, Integer k, Integer order)//order of P 447 | { 448 | if(P.identity) 449 | { 450 | R.identity=true; 451 | return R; 452 | } 453 | Point temp(false); 454 | R.identity=true; 455 | Point acc(P); 456 | if(order!=-1)//if order is known 457 | k=k%order;//better: k=k%order(P) 458 | while(k>0) 459 | { 460 | if(k%2) 461 | { 462 | /*if(k==1) 463 | { 464 | show(R); 465 | show(acc); 466 | }*/ 467 | add(temp,R,acc); 468 | R=temp; 469 | } 470 | Double(temp,acc); 471 | acc=temp; 472 | k=k/2; 473 | } 474 | return R; 475 | } 476 | bool ellipticCurveFq::verifyPoint(const Point &P) const 477 | { 478 | if(P.identity) 479 | return true; 480 | fieldElement rhs,x2,y2,x2pAx,x2pA,xpA,xpAx2,lhs,xy,cy; 481 | field->sqr(x2,P.x); 482 | field->sqr(y2,P.y); 483 | 484 | switch (ec->type) 485 | { 486 | case 0: 487 | field->add(x2pA,x2,ec->A); 488 | field->mul(x2pAx,x2pA,P.x); 489 | field->add(rhs,x2pAx,ec->B); 490 | /*field->writeElement(rhs)<writeElement(y2)<add(xpA,P.x,ec->A); 499 | field->mul(xpAx2,xpA,x2); 500 | field->add(rhs,xpAx2,ec->B); 501 | field->mul(xy,P.x,P.y); 502 | field->add(lhs,y2,xy); 503 | if(lhs==rhs) 504 | return true; 505 | else 506 | return false; 507 | case 2: 508 | field->add(x2pA,x2,ec->A); 509 | field->mul(x2pAx,x2pA,P.x); 510 | field->add(rhs,x2pAx,ec->B); 511 | field->mul(cy,ec->C,P.y); 512 | field->add(lhs,y2,cy); 513 | if(lhs==rhs) 514 | return true; 515 | else 516 | return false; 517 | default: 518 | return false; 519 | } 520 | } 521 | /*type 0: E/K, char(K)!=2: y2 = x3+ax+b, 522 | type 1: non-supersingular E/F2m: y2 + xy = x3+ax2+b, 523 | tyep 2: supersingular E/F2m: y2 + cy = x3 + ax + b*/ 524 | void ellipticCurveFq::show() 525 | { 526 | cout<<"Elliptic Curve Defined by "; 527 | switch(ec->type) 528 | { 529 | case 0: 530 | cout<<"y^2 = x^3 + "; 531 | field->writeElement(ec->A); 532 | cout<<"x + "; 533 | field->writeElement(ec->B); 534 | cout<writeElement(ec->A); 539 | cout<<"x^2 + "; 540 | field->writeElement(ec->B); 541 | cout<writeElement(ec->C); 546 | cout<<"y = x^3 + "; 547 | field->writeElement(ec->A); 548 | cout<<"x + "; 549 | field->writeElement(ec->B); 550 | cout<p<<"^"<m; 554 | cout<<" with irreducible polynomial "; 555 | field->writeElement(field->irred); 556 | cout<