summaryrefslogtreecommitdiff
path: root/xtrcrypt.cpp
blob: aa106aa44a200cdbaa3105c91fa371c41f4fadfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// xtrcrypt.cpp - originally written and placed in the public domain by Wei Dai

#include "pch.h"

#include "asn.h"
#include "integer.h"
#include "xtrcrypt.h"
#include "nbtheory.h"
#include "modarith.h"
#include "argnames.h"

NAMESPACE_BEGIN(CryptoPP)

XTR_DH::XTR_DH(const Integer &p, const Integer &q, const GFP2Element &g)
	: m_p(p), m_q(q), m_g(g)
{
}

XTR_DH::XTR_DH(RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits)
{
	XTR_FindPrimesAndGenerator(rng, m_p, m_q, m_g, pbits, qbits);
}

XTR_DH::XTR_DH(BufferedTransformation &bt)
{
	BERSequenceDecoder seq(bt);
	m_p.BERDecode(seq);
	m_q.BERDecode(seq);
	m_g.c1.BERDecode(seq);
	m_g.c2.BERDecode(seq);
	seq.MessageEnd();
}

void XTR_DH::DEREncode(BufferedTransformation &bt) const
{
	DERSequenceEncoder seq(bt);
	m_p.DEREncode(seq);
	m_q.DEREncode(seq);
	m_g.c1.DEREncode(seq);
	m_g.c2.DEREncode(seq);
	seq.MessageEnd();
}

bool XTR_DH::Validate(RandomNumberGenerator &rng, unsigned int level) const
{
	bool pass = true;
	pass = pass && m_p > Integer::One() && m_p.IsOdd();
	CRYPTOPP_ASSERT(pass);
	pass = pass && m_q > Integer::One() && m_q.IsOdd();
	CRYPTOPP_ASSERT(pass);
	GFP2Element three = GFP2_ONB<ModularArithmetic>(m_p).ConvertIn(3);
	CRYPTOPP_ASSERT(pass);
	pass = pass && !(m_g.c1.IsNegative() || m_g.c2.IsNegative() || m_g.c1 >= m_p || m_g.c2 >= m_p || m_g == three);
	CRYPTOPP_ASSERT(pass);
	if (level >= 1)
	{
		pass = pass && ((m_p.Squared()-m_p+1)%m_q).IsZero();
		CRYPTOPP_ASSERT(pass);
	}
	if (level >= 2)
	{
		pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
		CRYPTOPP_ASSERT(pass);
		pass = pass && XTR_Exponentiate(m_g, (m_p.Squared()-m_p+1)/m_q, m_p) != three;
		CRYPTOPP_ASSERT(pass);
		pass = pass && XTR_Exponentiate(m_g, m_q, m_p) == three;
		CRYPTOPP_ASSERT(pass);
	}
	return pass;
}

bool XTR_DH::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
	return GetValueHelper(this, name, valueType, pValue).Assignable()
		CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
		CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder)
		CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator)
		;
}

void XTR_DH::AssignFrom(const NameValuePairs &source)
{
	AssignFromHelper(this, source)
		CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
		CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder)
		CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupGenerator)
		;
}

void XTR_DH::GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
{
	Integer x(rng, Integer::Zero(), m_q-1);
	x.Encode(privateKey, PrivateKeyLength());
}

void XTR_DH::GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
{
	CRYPTOPP_UNUSED(rng);
	Integer x(privateKey, PrivateKeyLength());
	GFP2Element y = XTR_Exponentiate(m_g, x, m_p);
	y.Encode(publicKey, PublicKeyLength());
}

bool XTR_DH::Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey) const
{
	GFP2Element w(otherPublicKey, PublicKeyLength());
	if (validateOtherPublicKey)
	{
		GFP2_ONB<ModularArithmetic> gfp2(m_p);
		GFP2Element three = gfp2.ConvertIn(3);
		if (w.c1.IsNegative() || w.c2.IsNegative() || w.c1 >= m_p || w.c2 >= m_p || w == three)
			return false;
		if (XTR_Exponentiate(w, m_q, m_p) != three)
			return false;
	}
	Integer s(privateKey, PrivateKeyLength());
	GFP2Element z = XTR_Exponentiate(w, s, m_p);
	z.Encode(agreedValue, AgreedValueLength());
	return true;
}

NAMESPACE_END