1 // xtrcrypt.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 
5 #include "asn.h"
6 #include "integer.h"
7 #include "xtrcrypt.h"
8 #include "nbtheory.h"
9 #include "modarith.h"
10 #include "argnames.h"
11 
NAMESPACE_BEGIN(CryptoPP)12 NAMESPACE_BEGIN(CryptoPP)
13 
14 XTR_DH::XTR_DH(const Integer &p, const Integer &q, const GFP2Element &g)
15 	: m_p(p), m_q(q), m_g(g)
16 {
17 }
18 
XTR_DH(RandomNumberGenerator & rng,unsigned int pbits,unsigned int qbits)19 XTR_DH::XTR_DH(RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits)
20 {
21 	XTR_FindPrimesAndGenerator(rng, m_p, m_q, m_g, pbits, qbits);
22 }
23 
XTR_DH(BufferedTransformation & bt)24 XTR_DH::XTR_DH(BufferedTransformation &bt)
25 {
26 	BERSequenceDecoder seq(bt);
27 	m_p.BERDecode(seq);
28 	m_q.BERDecode(seq);
29 	m_g.c1.BERDecode(seq);
30 	m_g.c2.BERDecode(seq);
31 	seq.MessageEnd();
32 }
33 
DEREncode(BufferedTransformation & bt) const34 void XTR_DH::DEREncode(BufferedTransformation &bt) const
35 {
36 	DERSequenceEncoder seq(bt);
37 	m_p.DEREncode(seq);
38 	m_q.DEREncode(seq);
39 	m_g.c1.DEREncode(seq);
40 	m_g.c2.DEREncode(seq);
41 	seq.MessageEnd();
42 }
43 
Validate(RandomNumberGenerator & rng,unsigned int level) const44 bool XTR_DH::Validate(RandomNumberGenerator &rng, unsigned int level) const
45 {
46 	bool pass = true;
47 	pass = pass && m_p > Integer::One() && m_p.IsOdd();
48 	CRYPTOPP_ASSERT(pass);
49 	pass = pass && m_q > Integer::One() && m_q.IsOdd();
50 	CRYPTOPP_ASSERT(pass);
51 	GFP2Element three = GFP2_ONB<ModularArithmetic>(m_p).ConvertIn(3);
52 	CRYPTOPP_ASSERT(pass);
53 	pass = pass && !(m_g.c1.IsNegative() || m_g.c2.IsNegative() || m_g.c1 >= m_p || m_g.c2 >= m_p || m_g == three);
54 	CRYPTOPP_ASSERT(pass);
55 	if (level >= 1)
56 	{
57 		pass = pass && ((m_p.Squared()-m_p+1)%m_q).IsZero();
58 		CRYPTOPP_ASSERT(pass);
59 	}
60 	if (level >= 2)
61 	{
62 		pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
63 		CRYPTOPP_ASSERT(pass);
64 		pass = pass && XTR_Exponentiate(m_g, (m_p.Squared()-m_p+1)/m_q, m_p) != three;
65 		CRYPTOPP_ASSERT(pass);
66 		pass = pass && XTR_Exponentiate(m_g, m_q, m_p) == three;
67 		CRYPTOPP_ASSERT(pass);
68 	}
69 	return pass;
70 }
71 
GetVoidValue(const char * name,const std::type_info & valueType,void * pValue) const72 bool XTR_DH::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
73 {
74 	return GetValueHelper(this, name, valueType, pValue).Assignable()
75 		CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
76 		CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
77 		CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
78 		;
79 }
80 
AssignFrom(const NameValuePairs & source)81 void XTR_DH::AssignFrom(const NameValuePairs &source)
82 {
83 	AssignFromHelper(this, source)
84 		CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
85 		CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
86 		CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupGenerator)
87 		;
88 }
89 
GeneratePrivateKey(RandomNumberGenerator & rng,byte * privateKey) const90 void XTR_DH::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
91 {
92 	Integer x(rng, Integer::Zero(), m_q-1);
93 	x.Encode(privateKey, PrivateKeyLength());
94 }
95 
GeneratePublicKey(RandomNumberGenerator & rng,const byte * privateKey,byte * publicKey) const96 void XTR_DH::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
97 {
98 	CRYPTOPP_UNUSED(rng);
99 	Integer x(privateKey, PrivateKeyLength());
100 	GFP2Element y = XTR_Exponentiate(m_g, x, m_p);
101 	y.Encode(publicKey, PublicKeyLength());
102 }
103 
Agree(byte * agreedValue,const byte * privateKey,const byte * otherPublicKey,bool validateOtherPublicKey) const104 bool XTR_DH::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const
105 {
106 	GFP2Element w(otherPublicKey, PublicKeyLength());
107 	if (validateOtherPublicKey)
108 	{
109 		GFP2_ONB<ModularArithmetic> gfp2(m_p);
110 		GFP2Element three = gfp2.ConvertIn(3);
111 		if (w.c1.IsNegative() || w.c2.IsNegative() || w.c1 >= m_p || w.c2 >= m_p || w == three)
112 			return false;
113 		if (XTR_Exponentiate(w, m_q, m_p) != three)
114 			return false;
115 	}
116 	Integer s(privateKey, PrivateKeyLength());
117 	GFP2Element z = XTR_Exponentiate(w, s, m_p);
118 	z.Encode(agreedValue, AgreedValueLength());
119 	return true;
120 }
121 
122 NAMESPACE_END
123