3e93c4 | 2004-02-07 | Martin Nilsson | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
3e93c4 | 2004-02-07 | Martin Nilsson | | #pike __REAL_VERSION__
#pragma strict_types
|
e1fb09 | 2014-02-14 | Martin Nilsson | | #require constant(Crypto.Hash)
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
9104d0 | 2014-01-13 | Henrik Grubbström (Grubba) | | inherit Crypto.Sign;
|
119b8d | 2014-08-14 | Henrik Grubbström (Grubba) | |
string(8bit) name() { return "DSA"; }
class State {
inherit ::this_program;
|
53d1d3 | 2014-04-26 | Martin Nilsson | | protected string _sprintf(int t)
{
|
2037ab | 2014-04-30 | Martin Nilsson | | return t=='O' && sprintf("%O(%d,%d)", this_program, p->size(), q->size());
|
53d1d3 | 2014-04-26 | Martin Nilsson | | }
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
9eaf1d | 2008-06-28 | Martin Nilsson | | protected Gmp.mpz p;
protected Gmp.mpz q;
protected Gmp.mpz g;
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
9eaf1d | 2008-06-28 | Martin Nilsson | | protected Gmp.mpz y;
protected Gmp.mpz x;
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
b43231 | 2014-04-06 | Martin Nilsson | | protected function(int(0..):string(8bit)) random = .Random.random_string;
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | Gmp.mpz get_p() { return p; }
Gmp.mpz get_q() { return q; }
Gmp.mpz get_g() { return g; }
Gmp.mpz get_y() { return y; }
Gmp.mpz get_x() { return x; }
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
2d125d | 2004-02-07 | Martin Nilsson | |
|
b43231 | 2014-04-06 | Martin Nilsson | | this_program set_random(function(int(0..):string(8bit)) r)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
random = r;
return this;
}
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) name() { return "DSA"; }
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
this_program set_public_key(Gmp.mpz modulo, Gmp.mpz order,
Gmp.mpz generator, Gmp.mpz key)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | p = modulo;
q = order;
g = generator;
y = key;
return this;
|
3e93c4 | 2004-02-07 | Martin Nilsson | | }
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
int(0..1) public_key_equal(this_program dsa)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | return (p == dsa->get_p()) && (q == dsa->get_q()) &&
(g == dsa->get_g()) && (y == dsa->get_y());
|
3e93c4 | 2004-02-07 | Martin Nilsson | | }
|
7c383a | 2014-02-22 | Henrik Grubbström (Grubba) | |
protected int(0..1) _equal(mixed other)
{
if (!objectp(other) || (object_program(other) != object_program(this)) ||
!public_key_equal([object(this_program)]other)) {
return 0;
}
this_program dsa = [object(this_program)]other;
return x == dsa->get_x();
}
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
this_program set_private_key(Gmp.mpz secret)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | x = secret;
return this;
|
3e93c4 | 2004-02-07 | Martin Nilsson | | }
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
3f6dd0 | 2013-12-02 | Martin Nilsson | | #if !constant(Nettle.dsa_generate_keypair)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | #define SEED_LENGTH 20
|
387ff9 | 2013-12-19 | Martin Nilsson | | protected string(8bit) nist_hash(Gmp.mpz x)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) s = x->digits(256);
|
3e93c4 | 2004-02-07 | Martin Nilsson | | return .SHA1.hash(s[sizeof(s) - SEED_LENGTH..]);
}
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
protected array(Gmp.mpz) nist_primes(int l)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
if ( (l < 0) || (l > 8) )
error( "Unsupported key size.\n" );
int L = 512 + 64 * l;
int n = (L-1) / 160;
|
0423a8 | 2008-04-15 | Martin Nilsson | |
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
for (;;)
{
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) seed = random(SEED_LENGTH);
|
3e93c4 | 2004-02-07 | Martin Nilsson | | Gmp.mpz s = Gmp.mpz(seed, 256);
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) h = [string(8bit)]
|
78b5c9 | 2013-12-10 | Henrik Grubbström (Grubba) | | (nist_hash(s) ^ nist_hash( [object(Gmp.mpz)](s + 1) ));
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | h = sprintf("%c%s%c", h[0] | 0x80, h[1..<1], h[-1] | 1);
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
Gmp.mpz q = Gmp.mpz(h, 256);
|
ce0c2a | 2014-05-05 | Martin Nilsson | | if (!q->probably_prime_p())
|
3e93c4 | 2004-02-07 | Martin Nilsson | | continue;
int i, j;
for (i = 0, j = 2; i < 4096; i++, j += n+1)
{
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) buffer = "";
|
3e93c4 | 2004-02-07 | Martin Nilsson | | int k;
for (k = 0; k<= n; k++)
buffer = nist_hash( [object(Gmp.mpz)](s + j + k) ) + buffer;
buffer = buffer[sizeof(buffer) - L/8 ..];
|
387ff9 | 2013-12-19 | Martin Nilsson | | buffer[0] = [int(8bit)](buffer[0] | 0x80);
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
Gmp.mpz p = Gmp.mpz(buffer, 256);
p -= p % (2 * q) - 1;
|
ce0c2a | 2014-05-05 | Martin Nilsson | | if (p->probably_prime_p())
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
return ({ p, q });
}
}
}
}
|
9eaf1d | 2008-06-28 | Martin Nilsson | | protected Gmp.mpz find_generator(Gmp.mpz p, Gmp.mpz q)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
Gmp.mpz e = [object(Gmp.mpz)]((p - 1) / q);
Gmp.mpz g;
do
{
g = ([object(Gmp.mpz)](random_number( [object(Gmp.mpz)](p-3) ) + 2))
->powm(e, p);
}
while (g == 1);
return g;
}
|
3f6dd0 | 2013-12-02 | Martin Nilsson | |
protected void generate_parameters(int bits)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | if (!bits || bits % 64)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | error( "Unsupported key size.\n" );
[p, q] = nist_primes(bits / 64 - 8);
if (p % q != 1)
error( "Internal error.\n" );
if (q->size() != 160)
error( "Internal error.\n" );
g = find_generator(p, q);
if ( (g == 1) || (g->powm(q, p) != 1))
error( "Internal error.\n" );
|
3f6dd0 | 2013-12-02 | Martin Nilsson | | }
variant this_program generate_key(int p_bits, int q_bits)
{
if(q_bits!=160)
error("Only 1024/160 supported with Nettle version < 2.0\n");
generate_parameters(1024);
return generate_key();
}
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
3f6dd0 | 2013-12-02 | Martin Nilsson | | #else // !constant(Nettle.dsa_generate_keypair)
variant this_program generate_key(int p_bits, int q_bits)
{
[ p, q, g, y, x ] = Nettle.dsa_generate_keypair(p_bits, q_bits, random);
|
3e93c4 | 2004-02-07 | Martin Nilsson | | return this;
}
|
3f6dd0 | 2013-12-02 | Martin Nilsson | | #endif
|
3e93c4 | 2004-02-07 | Martin Nilsson | |
|
3f6dd0 | 2013-12-02 | Martin Nilsson | |
variant this_program generate_key()
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
if(!p || !q || !g) error("Public parameters not set..\n");
x = [object(Gmp.mpz)](random_number( [object(Gmp.mpz)](q-2) ) + 2);
y = g->powm(x, p);
return this;
}
|
3f6dd0 | 2013-12-02 | Martin Nilsson | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
#define Sequence Standards.ASN1.Types.Sequence
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | | #define Integer Standards.ASN1.Types.Integer
#define BitString Standards.ASN1.Types.BitString
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | |
Sequence pkcs_algorithm_identifier()
{
return
Sequence( ({ Standards.PKCS.Identifiers.dsa_id,
Sequence( ({ Integer(get_p()),
Integer(get_q()),
Integer(get_g())
}) )
}) );
}
|
0fbdf6 | 2014-01-11 | Henrik Grubbström (Grubba) | | Sequence pkcs_signature_algorithm_id(.Hash hash)
|
3e93c4 | 2004-02-07 | Martin Nilsson | | {
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | | switch(hash->name())
{
case "sha1":
return Sequence( ({ Standards.PKCS.Identifiers.dsa_sha_id }) );
break;
case "sha224":
return Sequence( ({ Standards.PKCS.Identifiers.dsa_sha224_id }) );
break;
case "sha256":
return Sequence( ({ Standards.PKCS.Identifiers.dsa_sha256_id }) );
break;
}
return 0;
|
3e93c4 | 2004-02-07 | Martin Nilsson | | }
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | Sequence pkcs_public_key()
{
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | | return Sequence(({
pkcs_algorithm_identifier(),
BitString(Integer(get_y())->get_der()),
}));
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | }
|
a2a39b | 2014-01-11 | Henrik Grubbström (Grubba) | | #undef BitString
#undef Integer
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | #undef Sequence
|
ee804c | 2013-11-21 | Martin Nilsson | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) pkcs_sign(string(8bit) message, .Hash h)
|
ee804c | 2013-11-21 | Martin Nilsson | | {
array sign = map(raw_sign(hash(message, h)), Standards.ASN1.Types.Integer);
return Standards.ASN1.Types.Sequence(sign)->get_der();
}
#define Object Standards.ASN1.Types.Object
|
387ff9 | 2013-12-19 | Martin Nilsson | | int(0..1) pkcs_verify(string(8bit) message, .Hash h, string(8bit) sign)
|
ee804c | 2013-11-21 | Martin Nilsson | | {
Object a = Standards.ASN1.Decode.simple_der_decode(sign);
|
0e0a0a | 2013-12-04 | Martin Nilsson | |
|
ee804c | 2013-11-21 | Martin Nilsson | | if (!a
|| (a->type_name != "SEQUENCE")
|| (sizeof([array]a->elements) != 2)
|| (sizeof( ([array(object(Object))]a->elements)->type_name -
({ "INTEGER" }))))
return 0;
return raw_verify(hash(message, h),
[object(Gmp.mpz)]([array(object(Object))]a->elements)[0]->
value,
[object(Gmp.mpz)]([array(object(Object))]a->elements)[1]->
value);
}
#undef Object
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
7f833d | 2014-04-12 | Henrik Grubbström (Grubba) | |
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | Gmp.mpz hash(string(8bit) msg, .Hash h)
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | {
|
387ff9 | 2013-12-19 | Martin Nilsson | | string(8bit) digest = h->hash(msg)[..q->size()/8-1];
|
8f18ae | 2013-11-22 | Martin Nilsson | | return [object(Gmp.mpz)](Gmp.mpz(digest, 256) % q);
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | }
protected Gmp.mpz random_number(Gmp.mpz n)
{
|
b43231 | 2014-04-06 | Martin Nilsson | | return [object(Gmp.mpz)](Gmp.mpz(random( [int(0..)](q->size() + 10 / 8)), 256) % n);
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | }
protected Gmp.mpz random_exponent()
{
return [object(Gmp.mpz)](random_number([object(Gmp.mpz)](q - 1)) + 1);
}
array(Gmp.mpz) raw_sign(Gmp.mpz h, void|Gmp.mpz k)
{
if(!k) k = random_exponent();
Gmp.mpz r = [object(Gmp.mpz)](g->powm(k, p) % q);
Gmp.mpz s = [object(Gmp.mpz)]((k->invert(q) * (h + x*r)) % q);
return ({ r, s });
}
int(0..1) raw_verify(Gmp.mpz h, Gmp.mpz r, Gmp.mpz s)
{
Gmp.mpz w;
if (catch
{
w = s->invert(q);
})
return 0;
return r == (g->powm( [object(Gmp.mpz)](w * h % q), p) *
y->powm( [object(Gmp.mpz)](w * r % q), p) % p) % q;
}
|
7f833d | 2014-04-12 | Henrik Grubbström (Grubba) | | int(0..) key_size()
{
return p->size();
}
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | __deprecated__ string(8bit) sign_rsaref(string(8bit) msg)
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | {
|
ee804c | 2013-11-21 | Martin Nilsson | | [Gmp.mpz r, Gmp.mpz s] = raw_sign(hash(msg, .SHA1));
|
b3e4a0 | 2013-10-28 | Martin Nilsson | |
|
d8519c | 2013-12-19 | Martin Nilsson | | return sprintf("%'\0'20s%'\0'20s", r->digits(256), s->digits(256));
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | }
|
387ff9 | 2013-12-19 | Martin Nilsson | | __deprecated__ int(0..1) verify_rsaref(string(8bit) msg, string(8bit) s)
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | {
if (sizeof(s) != 40)
return 0;
|
ee804c | 2013-11-21 | Martin Nilsson | | return raw_verify(hash(msg, .SHA1),
|
b3e4a0 | 2013-10-28 | Martin Nilsson | | Gmp.mpz(s[..19], 256),
Gmp.mpz(s[20..], 256));
}
|
5b7ecf | 2004-02-07 | Martin Nilsson | |
|
1321bc | 2013-11-22 | Henrik Grubbström (Grubba) | |
|
387ff9 | 2013-12-19 | Martin Nilsson | | __deprecated__ string(8bit) sign_ssl(string(8bit) msg)
|
ee804c | 2013-11-21 | Martin Nilsson | | {
return pkcs_sign(msg, .SHA1);
}
|
387ff9 | 2013-12-19 | Martin Nilsson | | __deprecated__ int(0..1) verify_ssl(string(8bit) msg, string(8bit) s)
|
ee804c | 2013-11-21 | Martin Nilsson | | {
return pkcs_verify(msg, .SHA1, s);
}
|
119b8d | 2014-08-14 | Henrik Grubbström (Grubba) | |
}
protected State `()()
{
return State();
}
|