~zooko/cryptopp/trunk

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