From: mdw Date: Sun, 4 Apr 2004 19:42:59 +0000 (+0000) Subject: Add set -e. X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/commitdiff_plain/e9026a0a6d8fc5cbcfa8d658176bfd2776cb550e Add set -e. --- diff --git a/.cvsignore b/.cvsignore index 8eae633..6aeb347 100644 --- a/.cvsignore +++ b/.cvsignore @@ -285,3 +285,7 @@ sha224-mgf.c sha224-mgf.h junk deb-build +has160-hmac.c +has160-hmac.h +has160-mgf.c +has160-mgf.h diff --git a/Makefile.m4 b/Makefile.m4 index bd832ab..3f2672d 100644 --- a/Makefile.m4 +++ b/Makefile.m4 @@ -1,6 +1,6 @@ ## -*-m4-*- ## -## $Id: Makefile.m4,v 1.78 2004/04/04 19:04:11 mdw Exp $ +## $Id: Makefile.m4,v 1.79 2004/04/04 19:42:59 mdw Exp $ ## ## Makefile for Catacomb ## @@ -29,6 +29,9 @@ ##----- Revision history ---------------------------------------------------- ## ## $Log: Makefile.m4,v $ +## Revision 1.79 2004/04/04 19:42:59 mdw +## Add set -e. +## ## Revision 1.78 2004/04/04 19:04:11 mdw ## Raw I/O of elliptic curve points and group elements. ## @@ -319,7 +322,7 @@ _(serpent) _(noekeon)') define(`cipher_modes', `_(ecb) _(cbc) _(cfb) _(ofb) _(counter)') define(`hashes', `dnl -_(md5) _(md4) _(md2) _(tiger) dnl +_(md5) _(md4) _(md2) _(tiger) _(has160) dnl _(sha) _(sha224) _(sha256) _(sha384) _(sha512) dnl _(rmd128) _(rmd160) _(rmd256) _(rmd320)') define(`hash_modes', `_(mgf) _(hmac)') @@ -367,8 +370,24 @@ ptab.c: ptab.in p-gentab.awk mpdump $(srcdir)/p-gentab.awk <$(srcdir)/ptab.in >ptab.c.new mv ptab.c.new ptab.c +gciphertab.c: gengctab + $(srcdir)/gengctab gccipher gcipher >gciphertab.c.new \ + "lit(join(`ciphers', `-', `cipher_modes')) \ + rc4 seal" + mv gciphertab.c.new gciphertab.c + +gmactab.c: gengctab + $(srcdir)/gengctab gcmac gmac >gmactab.c.new \ + "lit(join(`hashes', `-', `_(hmac)'))" + mv gmactab.c.new gmactab.c + +ghashtab.c: gengctab + $(srcdir)/gengctab gchash ghash >ghashtab.c.new \ + "lit(`hashes')" + mv ghashtab.c.new ghashtab.c + BUILT_SOURCES = \ - getdate.c modes-stamp \ + getdate.c modes-stamp gciphertab.c gmactab.c ghashtab.c \ addsuffix(join(`ciphers', `-', `cipher_modes'), `.c') \ addsuffix(join(`ciphers', `-', `cipher_modes'), `.h') \ addsuffix(join(`hashes', `-', `hash_modes'), `.c') \ @@ -393,7 +412,7 @@ pkginclude_HEADERS = \ gfx.h gf.h gfreduce.h gfn.h \ primetab.h pfilt.h rabin.h \ pgen.h prim.h strongprime.h limlee.h keycheck.h \ - bbs.h rsa.h dh.h dsarand.h dsa.h \ + bbs.h rsa.h dh.h dsarand.h dsa.h gdsa.h gkcdsa.h \ oaep.h pkcs1.h pss.h tlsprf.h sslprf.h \ gfshare.h share.h \ rho.h \ @@ -437,6 +456,7 @@ define(`PGEN_SOURCES', rsa-priv.c rsa-pub.c rsa-gen.c rsa-recover.c rsa-fetch.c \ dh-gen.c dh-limlee.c dh-check.c dh-fetch.c dh-param.c \ dsarand.c dsa-sign.c dsa-verify.c dsa-gen.c dsa-check.c \ + gdsa.c gkcdsa.c \ key-data.c key-flags.c key-text.c key-binary.c key-pass.c \ key-pack.c key-misc.c key-file.c key-attr.c key-io.c key-moan.c \ key-error.c key-fetch.c \ @@ -450,6 +470,7 @@ libcatacomb_la_SOURCES = \ oaep.c pkcs1.c pss.c tlsprf.c sslprf.c \ gfshare.c \ MP_SOURCES karatsuba.h \ + gciphertab.c ghashtab.c gmactab.c \ des-base.c des-base.h \ desx-tab.h \ rc2-tab.h \ @@ -543,7 +564,7 @@ man_MANS = key.1 hashsum.1 keyring.5 pixie.1 ## --- Other handy definitions --- EXTRA_DIST = \ - Makefile.m4 genmodes $(man_MANS) xpixie group-test.c \ + Makefile.m4 genmodes gengctab $(man_MANS) xpixie group-test.c \ ectab.in ec-gentab.awk ptab.in p-gentab.awk \ README.cipher README.hash README.random README.mp \ debian/rules debian/copyright debian/control debian/changelog \ @@ -551,7 +572,9 @@ EXTRA_DIST = \ debian/catacomb-bin.prerm debian/catacomb-bin.templates dist-hook: - @ln getdate.c $(distdir) || ln $(srcdir)/getdate.c $(distdir) || true + @for i in getdate.c gciphertab.c ghashtab.c gmactab.c; do \ + ln $$i $(distdir) || ln $(srcdir)/$$i $(distdir) || true; \ + done @echo datestamp >$(distdir)/modes-stamp || true @for i in calc tests; do \ mkdir $(distdir)/$$i; \ @@ -618,6 +641,8 @@ CTESTRIG(ec-test) CTESTRIG(ec-info) CTESTRIG(dh-param) CTESTRIG(group-test) +CTESTRIG(gdsa) +CTESTRIG(gkcdsa) CTESTRIG(pgen) CTESTRIG(dsa-gen) CTESTRIG(dsa-sign) diff --git a/dsig.c b/dsig.c index c5eb5af..6a67990 100644 --- a/dsig.c +++ b/dsig.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: dsig.c,v 1.7 2001/02/23 09:04:17 mdw Exp $ + * $Id: dsig.c,v 1.8 2004/04/04 19:42:59 mdw Exp $ * * Verify signatures on distribuitions of files * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: dsig.c,v $ + * Revision 1.8 2004/04/04 19:42:59 mdw + * Add set -e. + * * Revision 1.7 2001/02/23 09:04:17 mdw * Add new hash functions. Provide full help for subcommands. Run the * hash function over parts of the header in a canonical order. @@ -83,19 +86,6 @@ #include "rsa.h" #include "pkcs1.h" -#include "md2.h" -#include "md4.h" -#include "md5.h" -#include "rmd128.h" -#include "rmd160.h" -#include "rmd256.h" -#include "rmd320.h" -#include "sha.h" -#include "sha256.h" -#include "sha384.h" -#include "sha512.h" -#include "tiger.h" - /*----- Digital signature algorithm ---------------------------------------*/ static int dsasign(key *k, const void *m, size_t msz, dstr *d) @@ -206,9 +196,6 @@ typedef struct sig { const void */*s*/, size_t /*ssz*/); } sig; -static const gchash *hashtab[] = { - &rmd160, &tiger, &sha, &sha256, &sha384, &sha512, - &rmd128, &rmd256, &rmd320, &md5, &md4, &md2, 0 }; static sig sigtab[] = { { "dsa", "dsig-dsa", dsasign, dsaverify }, { "rsa", "dsig-rsa", rsasign, rsaverify }, @@ -226,9 +213,9 @@ static sig sigtab[] = { static const gchash *gethash(const char *name) { - const gchash **g, *gg = 0; + const gchash *const *g, *gg = 0; size_t sz = strlen(name); - for (g = hashtab; *g; g++) { + for (g = ghashtab; *g; g++) { if (strncmp(name, (*g)->name, sz) == 0) { if ((*g)->name[sz] == 0) { gg = *g; diff --git a/gdsa.c b/gdsa.c new file mode 100644 index 0000000..8723847 --- /dev/null +++ b/gdsa.c @@ -0,0 +1,264 @@ +/* -*-c-*- + * + * $Id: gdsa.c,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * Generalized version of DSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: gdsa.c,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gdsa.h" +#include "group.h" +#include "ghash.h" +#include "mpbarrett.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@. + */ + +ghash *gdsa_beginhash(const gdsa *c) { return (GH_INIT(c->h)); } + +/* --- @gdsa_endhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that DSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +void gdsa_endhash(gdsa *c, ghash *h) { ; } + +/* --- @gdsa_sign@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @gdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +void gdsa_sign(const gdsa *c, gdsa_sig *s, const void *m, mp *k) +{ + group *g = c->g; + mp *mr = mp_loadb(MP_NEW, m, c->h->hashsz); + ge *z = G_CREATE(g); + mp *sr = s->r, *ss = s->s; + mpbarrett b; + + if (k) { MP_COPY(k); goto have_k; } +new_k: + k = mprand_range(k, g->r, c->r, 0); +have_k: + if (MP_ISZERO(k)) goto new_k; + G_EXP(g, z, g->g, k); + sr = G_TOINT(g, sr, z); assert(sr); + if (MP_ISZERO(sr)) goto new_k; + + mp_div(0, &sr, sr, g->r); + mpbarrett_create(&b, g->r); + ss = mp_mul(ss, sr, c->u); ss = mpbarrett_reduce(&b, ss, ss); + ss = mp_add(ss, ss, mr); mp_div(0, &ss, ss, g->r); + mp_gcd(0, 0, &k, g->r, k); + ss = mp_mul(ss, ss, k); ss = mpbarrett_reduce(&b, ss, ss); + s->r = sr; s->s = ss; + mp_drop(k); mp_drop(mr); mpbarrett_destroy(&b); G_DESTROY(g, z); +} + +/* --- @gdsa_verify@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @const gdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@ and @h@. + */ + +int gdsa_verify(const gdsa *c, const gdsa_sig *s, const void *m) +{ + group *g = c->g; + group_expfactor e[2]; + mpbarrett b; + mp *h = MP_NEW, *t; + ge *w; + int rc = -1; + + if (MP_CMP(s->r, <, MP_ONE) || MP_CMP(s->r, >=, g->r) || + MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) + return (-1); + mpbarrett_create(&b, g->r); mp_gcd(0, 0, &h, g->r, s->s); + e[0].base = g->g; e[1].base = c->p; + t = mp_loadb(MP_NEW, m, c->h->hashsz); mp_div(0, &t, t, g->r); + t = mp_mul(t, t, h); e[0].exp = t = mpbarrett_reduce(&b, t, t); + h = mp_mul(h, s->r, h); e[1].exp = h = mpbarrett_reduce(&b, h, h); + w = G_CREATE(g); G_MEXP(g, w, e, 2); + t = G_TOINT(g, t, w); if (!t) goto done; + mp_div(0, &t, t, g->r); if (MP_EQ(t, s->r)) rc = 0; +done: + G_DESTROY(g, w); mp_drop(t); mp_drop(h); mpbarrett_destroy(&b); + return (rc); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static group *getgroup(const char *p) { + group *g; qd_parse qd; + qd.p = p; qd.e = 0; g = group_parse(&qd); + if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } + if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, + p, qd.p, qd.e); exit(1); } + return (g); +} + +static ge *getge(group *g, const char *p) { + ge *x = G_CREATE(g); + if (group_readstring(g, x, p, 0)) { + fprintf(stderr, "bad group element `%s'\n", p); + exit(1); + } + return (x); +} + +static void showge(group *g, const char *p, ge *x) { + fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); + putc('\n', stderr); +} + +static void showmp(const char *p, mp *x, int r) { + fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); + putc('\n', stderr); +} + +static int tsign(dstr *v) +{ + gdsa c; + gdsa_sig s, ss = GDSA_SIG_INIT; + ghash *h; + mp *k; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; + s.r = *(mp **)v[5].buf; s.s = *(mp **)v[6].buf; + + h = gdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gdsa_endhash(&c, h); + gdsa_sign(&c, &ss, GH_DONE(h, 0), k); + if (!MP_EQ(s.r, ss.r) || !MP_EQ(s.s, ss.s)) { + ok = 0; + fprintf(stderr, "*** sign failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showmp("private key", c.u, 16); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + showmp("computed r", ss.r, 16); showmp("computed s", ss.s, 16); + showmp("expected r", s.r, 16); showmp("expected s", s.s, 16); + } + mp_drop(s.r); mp_drop(s.s); mp_drop(ss.r); mp_drop(ss.s); + mp_drop(k); mp_drop(c.u); G_DESTROYGROUP(c.g); GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tverify(dstr *v) +{ + gdsa c; + gdsa_sig s; + ghash *h; + int rc, erc; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.p = getge(c.g, v[2].buf); + s.r = *(mp **)v[4].buf; s.s = *(mp **)v[5].buf; + erc = *(int *)v[6].buf; + + h = gdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gdsa_endhash(&c, h); + rc = gdsa_verify(&c, &s, GH_DONE(h, 0)); + if (!rc != !erc) { + ok = 0; + fprintf(stderr, "*** verify failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + showmp("sig r", s.r, 16); showmp("sig s", s.s, 16); + fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); + } + mp_drop(s.r); mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); + GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static const test_chunk tests[] = { + { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, + &type_mp, &type_mp, &type_mp } }, + { "verify", tverify, { &type_string, &type_string, &type_string, + &type_string, &type_mp, &type_mp, &type_int } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/tests/gdsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/gdsa.h b/gdsa.h new file mode 100644 index 0000000..6d88a4d --- /dev/null +++ b/gdsa.h @@ -0,0 +1,140 @@ +/* -*-c-*- + * + * $Id: gdsa.h,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * Generalized version of DSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: gdsa.h,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +#ifndef CATACOMB_GDSA_H +#define CATACOMB_GDSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- GDSA context --- * + * + * You don't need to fill in all of this stuff. See the description of the + * function you want to use to find out what members are needed. + */ + +typedef struct gdsa { + group *g; /* The group we work in */ + mp *u; /* Private key, for signing */ + ge *p; /* Public key, for verifying */ + grand *r; /* Random number source */ + const gchash *h; /* Hash function */ +} gdsa; + +/* --- GDSA signatures --- */ + +typedef struct gdsa_sig { mp *r, *s; } gdsa_sig; +#define GDSA_SIG_INIT { MP_NEW, MP_NEW } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@. + */ + +extern ghash *gdsa_beginhash(const gdsa */*c*/); + +/* --- @gdsa_endhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that DSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +extern void gdsa_endhash(gdsa */*c*/, ghash */*h*/); + +/* --- @gdsa_sign@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @gdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +extern void gdsa_sign(const gdsa */*c*/, gdsa_sig */*s*/, + const void */*m*/, mp */*k*/); + +/* --- @gdsa_verify@ --- * + * + * Arguments: @const gdsa *c@ = my context structure + * @const gdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +extern int gdsa_verify(const gdsa */*c*/, const gdsa_sig */*s*/, + const void */*m*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/genmodes b/genmodes index e08e710..76b82a6 100755 --- a/genmodes +++ b/genmodes @@ -1,5 +1,6 @@ #! /bin/sh +set -e baselist=$1 extlist=$2 diff --git a/ghash-def.h b/ghash-def.h index 9065f5b..da4063d 100644 --- a/ghash-def.h +++ b/ghash-def.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: ghash-def.h,v 1.5 2001/01/25 21:39:58 mdw Exp $ + * $Id: ghash-def.h,v 1.6 2004/04/04 19:42:59 mdw Exp $ * * Definitions for generic hash interface * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: ghash-def.h,v $ + * Revision 1.6 2004/04/04 19:42:59 mdw + * Add set -e. + * * Revision 1.5 2001/01/25 21:39:58 mdw * Burn the hash context when it's done with, for paranoia's sake. * @@ -134,7 +137,7 @@ static ghash *ghcopy(ghash *h) \ \ static const ghash_ops gops = \ { &pre, ghhash, ghdone, ghdestroy, ghcopy }; \ -const gchash pre = { #pre, PRE##_HASHSZ, ghinit }; +const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ }; /*----- That's all, folks -------------------------------------------------*/ diff --git a/gkcdsa.c b/gkcdsa.c new file mode 100644 index 0000000..f7119f5 --- /dev/null +++ b/gkcdsa.c @@ -0,0 +1,320 @@ +/* -*-c-*- + * + * $Id: gkcdsa.c,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * Generalized version of KCDSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: gkcdsa.c,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "gkcdsa.h" +#include "group.h" +#include "ghash.h" +#include "mpbarrett.h" +#include "mprand.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@, @g@ and @p@. + */ + +ghash *gkcdsa_beginhash(const gkcdsa *c) +{ + ghash *h = GH_INIT(c->h); + mp *v = G_TOINT(c->g, MP_NEW, c->p); + size_t sz = c->h->bufsz; + void *p = xmalloc(sz); + + if (/*ouch*/ !v) memset(p, 0, sz); + else mp_storeb(v, p, sz); + GH_HASH(h, p, sz); + mp_drop(v); xfree(p); + return (h); +} + +/* --- @gkcdsa_endhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that KCDSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +void gkcdsa_endhash(gkcdsa *c, ghash *h) { ; } + +/* --- @hashge@ --- * + * + * Arguments: @group *g@ = abstract group + * @const gchash *hc@ = hash class + * @ge *w@ = a group element + * + * Returns: A hash context, with the hash of @w@ in it. + */ + +static ghash *hashge(group *g, const gchash *hc, ge *w) +{ + ghash *h; + size_t sz; + void *p; + buf b; + int rc; + + sz = hc->hashsz; + if (sz < g->noctets) + sz = g->noctets; + p = xmalloc(sz); + buf_init(&b, p, sz); + rc = G_TORAW(g, &b, w); + assert(rc == 0); + h = GH_INIT(hc); + GH_HASH(h, BBASE(&b), BLEN(&b)); + xfree(p); + return (h); +} + +/* --- @gkcdsa_sign@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @gkcdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +void gkcdsa_sign(const gkcdsa *c, gkcdsa_sig *s, const void *m, mp *k) +{ + group *g = c->g; + mp *x, *y; + ge *z = G_CREATE(g); + size_t hsz = c->h->hashsz; + ghash *h; + + if (k) { MP_COPY(k); goto have_k; } +new_k: + k = mprand_range(k, g->r, c->r, 0); +have_k: + if (MP_ISZERO(k)) goto new_k; + G_EXP(g, z, g->g, k); + if (!s->r) s->r = xmalloc(hsz); + h = hashge(g, c->h, z); GH_DONE(h, s->r); + + x = mp_loadb(s->s, m, hsz); + y = mp_loadb(MP_NEW, s->r, hsz); + x = mp_xor(x, x, y); + mp_div(0, &x, x, g->r); + x = mp_sub(x, g->r, x); + x = mp_add(x, x, k); + if (MP_CMP(x, >=, g->r)) x = mp_sub(x, x, g->r); + x = mp_mul(x, x, c->u); mp_div(0, &x, x, g->r); + s->s = x; + mp_drop(k); mp_drop(y); GH_DESTROY(h); G_DESTROY(g, z); +} + +/* --- @gkcdsa_verify@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @const gkcdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +int gkcdsa_verify(const gkcdsa *c, const gkcdsa_sig *s, const void *m) +{ + group *g = c->g; + size_t hsz = c->h->hashsz; + group_expfactor e[2]; + mp *x, *y; + ghash *h; + ge *z; + octet *p; + int rc = -1; + + if (MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r)) + return (-1); + x = mp_loadb(MP_NEW, m, hsz); y = mp_loadb(MP_NEW, s->r, hsz); + x = mp_xor(x, x, y); mp_div(0, &x, x, g->r); + e[0].base = c->p; e[0].exp = s->s; + e[1].base = g->g; e[1].exp = x; + z = G_CREATE(g); G_MEXP(g, z, e, 2); + h = hashge(g, c->h, z); p = GH_DONE(h, 0); + if (memcmp(p, s->r, hsz) == 0) rc = 0; + mp_drop(x); mp_drop(y); G_DESTROY(g, z); GH_DESTROY(h); + return (rc); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +static group *getgroup(const char *p) { + group *g; qd_parse qd; + qd.p = p; qd.e = 0; g = group_parse(&qd); + if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; } + if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p, + p, qd.p, qd.e); exit(1); } + return (g); +} + +static ge *getge(group *g, const char *p) { + ge *x = G_CREATE(g); + if (group_readstring(g, x, p, 0)) { + fprintf(stderr, "bad group element `%s'\n", p); + exit(1); + } + return (x); +} + +static void showge(group *g, const char *p, ge *x) { + fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr); + putc('\n', stderr); +} + +static void showmp(const char *p, mp *x, int r) { + fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); + putc('\n', stderr); +} + +static int tsign(dstr *v) +{ + gdsa c; + gkcdsa_sig s, ss = GKCDSA_SIG_INIT; + ghash *h; + mp *k; + dstr d = DSTR_INIT; + mp *x; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf; + s.r = (octet *)v[5].buf; s.s = *(mp **)v[6].buf; + DENSURE(&d, c.h->hashsz); d.len = c.h->hashsz; memset(d.buf, 0, d.len); + ss.r = (octet *)d.buf; + + x = MP_NEW; mp_gcd(0, 0, &x, c.g->r, c.u); + c.p = G_CREATE(c.g); G_EXP(c.g, c.p, c.g->g, x); + h = gkcdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gkcdsa_endhash(&c, h); + gkcdsa_sign(&c, &ss, GH_DONE(h, 0), k); + if (memcmp(s.r, ss.r, c.h->hashsz) || !MP_EQ(s.s, ss.s)) { + ok = 0; + fprintf(stderr, "*** sign failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showmp("private key", c.u, 16); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + fprintf(stderr, "*** computed r = "); + type_hex.dump(&d, stderr); putc('\n', stderr); + showmp("computed s", ss.s, 16); + fprintf(stderr, "*** computed r = "); + type_hex.dump(&v[5], stderr); putc('\n', stderr); + showmp("expected s", s.s, 16); + } + mp_drop(s.s); dstr_destroy(&d); mp_drop(ss.s); mp_drop(x); mp_drop(k); + mp_drop(c.u); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static int tverify(dstr *v) +{ + gkcdsa c; + gkcdsa_sig s; + ghash *h; + int rc, erc; + int ok = 1; + + c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf); + c.p = getge(c.g, v[2].buf); + s.r = (octet *)v[4].buf; s.s = *(mp **)v[5].buf; + erc = *(int *)v[6].buf; + + h = gkcdsa_beginhash(&c); + GH_HASH(h, v[3].buf, v[3].len); + gkcdsa_endhash(&c, h); + rc = gkcdsa_verify(&c, &s, GH_DONE(h, 0)); + if (!rc != !erc) { + ok = 0; + fprintf(stderr, "*** verify failed!\n"); + fprintf(stderr, "*** group: %s\n", v[0].buf); + fprintf(stderr, "*** hash: %s\n", c.h->name); + showge(c.g, "public key", c.p); + fprintf(stderr, "*** message: `%s'\n", v[3].buf); + fprintf(stderr, "*** sig r = "); + type_hex.dump(&v[4], stderr); putc('\n', stderr); + showmp("sig s", s.s, 16); + fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail"); + } + mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); + GH_DESTROY(h); + assert(mparena_count(MPARENA_GLOBAL) == 0); + return (ok); +} + +static const test_chunk tests[] = { + { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string, + &type_mp, &type_hex, &type_mp } }, + { "verify", tverify, { &type_string, &type_string, &type_string, + &type_string, &type_hex, &type_mp, &type_int } }, + { 0 } +}; + +int main(int argc, char *argv[]) +{ + sub_init(); + test_run(argc, argv, tests, SRCDIR "/tests/gkcdsa"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/gkcdsa.h b/gkcdsa.h new file mode 100644 index 0000000..8901b87 --- /dev/null +++ b/gkcdsa.h @@ -0,0 +1,140 @@ +/* -*-c-*- + * + * $Id: gkcdsa.h,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * Generalized version of KCDSA + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: gkcdsa.h,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +#ifndef CATACOMB_GKCDSA_H +#define CATACOMB_GKCDSA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef CATACOMB_GROUP_H +# include "group.h" +#endif + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +#ifndef CATACOMB_GDSA_H +# include "gdsa.h" +#endif + +/*----- Data structures ---------------------------------------------------*/ + +/* --- Careful! --- * + * + * These structures are the same as for DSA. However, the private key @u@ is + * the %$\emph{inverse}$% of the exponent. Do this wrong and the maths will + * fail hopelessly. + */ + +typedef gdsa gkcdsa; + +typedef struct gkcdsa_sig { + octet *r; /* Null means @xmalloc@ me */ + mp *s; +} gkcdsa_sig; +#define GKCDSA_SIG_INIT { 0, 0 } + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @gdsa_beginhash@ --- * + * + * Arguments: @const gdsa *c@ = pointer to the context structure + * + * Returns: A hashing context for you to hash the message. + * + * Use: Initializes a hash function correctly for you to hash a + * message. Requires @h@, @g@ and @p@. + */ + +extern ghash *gkcdsa_beginhash(const gkcdsa */*c*/); + +/* --- @gkcdsa_endhash@ --- * + * + * Arguments: @const gkcdsa *c@ = pointer to the context structure + * @ghash *h@ = the hashing context + * + * Returns: --- + * + * Use: Does any final thing that KCDSA wants to do when hashing a + * message. (Actually, there's nothing.) The hashing context + * isn't finalized. + */ + +extern void gkcdsa_endhash(gkcdsa */*c*/, ghash */*h*/); + +/* --- @gkcdsa_sign@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @gkcdsa_sig *s@ = where to put the signature (initialized) + * @const void *m@ = pointer to message hash + * @mp *k@ = random exponent for this message or null + * + * Returns: --- + * + * Use: Signs a message. Requires @g@, @u@, @h@, and @r@ if @k@ is + * null. This is a better idea than inventing @k@ yourself. + */ + +extern void gkcdsa_sign(const gkcdsa */*c*/, gkcdsa_sig */*s*/, + const void */*m*/, mp */*k*/); + +/* --- @gkcdsa_verify@ --- * + * + * Arguments: @const gkcdsa *c@ = my context structure + * @const gkcdsa_sig *s@ = the signature to verify + * @const void *m@ = pointer to message hash + * + * Returns: Zero if OK, negative on failure. + * + * Use: Checks a signature on a message, Requires @g@, @p@, @h@. + */ + +extern int gkcdsa_verify(const gkcdsa */*c*/, const gkcdsa_sig */*s*/, + const void */*m*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/has160.c b/has160.c new file mode 100644 index 0000000..7c7b7b9 --- /dev/null +++ b/has160.c @@ -0,0 +1,256 @@ +/* -*-c-*- + * + * $Id: has160.c,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * The HAS160 message digest function + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: has160.c,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "ghash.h" +#include "ghash-def.h" +#include "hash.h" +#include "has160.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @has160_compress@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: HAS160 compression function. + */ + +void has160_compress(has160_ctx *ctx, const void *sbuf) +{ + uint32 a, b, c, d, e; + uint32 buf[16]; + + /* --- Fetch the chaining variables --- */ + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + /* --- Fetch the buffer contents --- */ + + { + int i; + const octet *p; + + for (i = 0, p = sbuf; i < 16; i++, p += 4) + buf[i] = LOAD32_L(p); + } + + /* --- Definitions for round functions --- */ + +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define G(x, y, z) ((x) ^ (y) ^ (z)) +#define H(x, y, z) ((y) ^ ((x) | ~(z))) + +#define FF(f, a, b, c, d, e, x, s, ss, k) do { \ + e += ROL32(a, s) + f(b, c, d) + (x) + k; \ + b = ROL32(b, ss); \ +} while (0) + + /* --- The actual hashing --- * + * + * Hmm, this is more regular than most. The macros are quite grim, + * though. + */ + +#define ROUND(f, ss, k, \ + i0, i1, i2, i3, i4, i5, i6, i7, \ + i8, i9, i10, i11, i12, i13, i14, i15) do { \ + FF(f, a, b, c, d, e, buf[ i8]^buf[ i9]^buf[i10]^buf[i11], 5, ss, k); \ + FF(f, e, a, b, c, d, buf[ i0], 11, ss, k); \ + FF(f, d, e, a, b, c, buf[ i1], 7, ss, k); \ + FF(f, c, d, e, a, b, buf[ i2], 15, ss, k); \ + FF(f, b, c, d, e, a, buf[ i3], 6, ss, k); \ + FF(f, a, b, c, d, e, buf[i12]^buf[i13]^buf[i14]^buf[i15], 13, ss, k); \ + FF(f, e, a, b, c, d, buf[ i4], 8, ss, k); \ + FF(f, d, e, a, b, c, buf[ i5], 14, ss, k); \ + FF(f, c, d, e, a, b, buf[ i6], 7, ss, k); \ + FF(f, b, c, d, e, a, buf[ i7], 12, ss, k); \ + FF(f, a, b, c, d, e, buf[ i0]^buf[ i1]^buf[ i2]^buf[ i3], 9, ss, k); \ + FF(f, e, a, b, c, d, buf[ i8], 11, ss, k); \ + FF(f, d, e, a, b, c, buf[ i9], 8, ss, k); \ + FF(f, c, d, e, a, b, buf[i10], 15, ss, k); \ + FF(f, b, c, d, e, a, buf[i11], 6, ss, k); \ + FF(f, a, b, c, d, e, buf[ i4]^buf[ i5]^buf[ i6]^buf[ i7], 12, ss, k); \ + FF(f, e, a, b, c, d, buf[i12], 9, ss, k); \ + FF(f, d, e, a, b, c, buf[i13], 14, ss, k); \ + FF(f, c, d, e, a, b, buf[i14], 5, ss, k); \ + FF(f, b, c, d, e, a, buf[i15], 13, ss, k); \ +} while (0) + + ROUND(F, 10, 0x00000000, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + ROUND(G, 17, 0x5a827999, + 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0); + ROUND(H, 25, 0x6ed9eba1, + 12, 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3); + ROUND(G, 30, 0x8f1bbcdc, + 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5, 0, 11, 6, 1, 12); + + /* --- Update the chaining variables --- */ + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; +} + +/* --- @has160_init@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +void has160_init(has160_ctx *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + ctx->off = 0; + ctx->nl = ctx->nh = 0; +} + +/* --- @has160_set@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +void has160_set(has160_ctx *ctx, const void *buf, unsigned long count) +{ + const octet *p = buf; + ctx->a = LOAD32_L(p + 0); + ctx->b = LOAD32_L(p + 4); + ctx->c = LOAD32_L(p + 8); + ctx->d = LOAD32_L(p + 12); + ctx->e = LOAD32_L(p + 16); + ctx->off = 0; + ctx->nl = U32(count); + ctx->nh = U32(((count & ~MASK32) >> 16) >> 16); +} + +/* --- @has160_hash@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +void has160_hash(has160_ctx *ctx, const void *buf, size_t sz) +{ + HASH_BUFFER(HAS160, has160, ctx, buf, sz); +} + +/* --- @has160_done@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +void has160_done(has160_ctx *ctx, void *hash) +{ + octet *p = hash; + HASH_MD5STRENGTH(HAS160, has160, ctx); + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); +} + +/* --- @has160_state@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @has160_set@. + */ + +unsigned long has160_state(has160_ctx *ctx, void *state) +{ + octet *p = state; + STORE32_L(p + 0, ctx->a); + STORE32_L(p + 4, ctx->b); + STORE32_L(p + 8, ctx->c); + STORE32_L(p + 12, ctx->d); + STORE32_L(p + 16, ctx->e); + return (ctx->nl | ((ctx->nh << 16) << 16)); +} + +/* --- Generic interface --- */ + +GHASH_DEF(HAS160, has160) + +/* --- Test code --- */ + +HASH_TEST(HAS160, has160) + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/has160.h b/has160.h new file mode 100644 index 0000000..f60fdc9 --- /dev/null +++ b/has160.h @@ -0,0 +1,167 @@ +/* -*-c-*- + * + * $Id: has160.h,v 1.1 2004/04/04 19:42:59 mdw Exp $ + * + * The HAS160 message digest function + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: has160.h,v $ + * Revision 1.1 2004/04/04 19:42:59 mdw + * Add set -e. + * + */ + +/*----- Notes on the HAS160 hash function ---------------------------------* + * + * HAS160 was designed by Chae Hoon Lim and the Korean Information Security + * Agency (KISA). It's recommended for use with KCDSA (though I think I'm + * happer with RIPEMD-160 or SHA1). It's here so I can check KCDSA test + * vectors. + */ + +#ifndef CATACOMB_HAS160_H +#define CATACOMB_HAS160_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +#ifndef CATACOMB_GHASH_H +# include "ghash.h" +#endif + +/*----- Magic numbers -----------------------------------------------------*/ + +#define HAS160_BUFSZ 64 +#define HAS160_HASHSZ 20 +#define HAS160_STATESZ 20 + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct has160_ctx { + uint32 a, b, c, d, e; /* Chaining variables */ + uint32 nl, nh; /* Byte count so far */ + unsigned off; /* Offset into buffer */ + octet buf[HAS160_BUFSZ]; /* Accumulation buffer */ +} has160_ctx; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @has160_compress@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *sbuf@ = pointer to buffer of appropriate size + * + * Returns: --- + * + * Use: HAS160 compression function. + */ + +extern void has160_compress(has160_ctx */*ctx*/, const void */*sbuf*/); + +/* --- @has160_init@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block to initialize + * + * Returns: --- + * + * Use: Initializes a context block ready for hashing. + */ + +extern void has160_init(has160_ctx */*ctx*/); + +/* --- @has160_set@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = pointer to state buffer + * @unsigned long count@ = current count of bytes processed + * + * Returns: --- + * + * Use: Initializes a context block from a given state. This is + * useful in cases where the initial hash state is meant to be + * secret, e.g., for NMAC and HMAC support. + */ + +extern void has160_set(has160_ctx */*ctx*/, const void */*buf*/, + unsigned long /*count*/); + +/* --- @has160_hash@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @const void *buf@ = buffer of data to hash + * @size_t sz@ = size of buffer to hash + * + * Returns: --- + * + * Use: Hashes a buffer of data. The buffer may be of any size and + * alignment. + */ + +extern void has160_hash(has160_ctx */*ctx*/, + const void */*buf*/, size_t /*sz*/); + +/* --- @has160_done@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context block + * @void *hash@ = pointer to output buffer + * + * Returns: --- + * + * Use: Returns the hash of the data read so far. + */ + +extern void has160_done(has160_ctx */*ctx*/, void */*hash*/); + +/* --- @has160_state@ --- * + * + * Arguments: @has160_ctx *ctx@ = pointer to context + * @void *state@ = pointer to buffer for current state + * + * Returns: Number of bytes written to the hash function so far. + * + * Use: Returns the current state of the hash function such that + * it can be passed to @has160_set@. + */ + +extern unsigned long has160_state(has160_ctx */*ctx*/, void */*state*/); + +/*----- Generic hash interface --------------------------------------------*/ + +extern const gchash has160; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hashsum.c b/hashsum.c index f2ced4b..11a5d37 100644 --- a/hashsum.c +++ b/hashsum.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: hashsum.c,v 1.8 2001/04/19 18:26:33 mdw Exp $ + * $Id: hashsum.c,v 1.9 2004/04/04 19:42:59 mdw Exp $ * * Hash files using some secure hash function * @@ -30,6 +30,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: hashsum.c,v $ + * Revision 1.9 2004/04/04 19:42:59 mdw + * Add set -e. + * * Revision 1.8 2001/04/19 18:26:33 mdw * Add CRC as another hash function. * @@ -79,30 +82,8 @@ #include "ghash.h" -#include "crc32.h" -#include "md2.h" -#include "md4.h" -#include "md5.h" -#include "rmd128.h" -#include "rmd160.h" -#include "rmd256.h" -#include "rmd320.h" -#include "sha.h" -#include "sha256.h" -#include "sha384.h" -#include "sha512.h" -#include "tiger.h" - /*----- Static variables --------------------------------------------------*/ -static const gchash *hashtab[] = { - &md5, &md4, &md2, - &sha, &sha256, &sha384, &sha512, - &rmd128, &rmd160, &rmd256, &rmd320, - &tiger, &gcrc32, - 0 -}; - #define f_binary 1u #define f_bogus 2u #define f_verbose 4u @@ -212,9 +193,9 @@ static size_t gethex(const char *p, octet *q, size_t sz, char **pp) static const gchash *gethash(const char *name) { - const gchash **g, *gg = 0; + const gchash *const *g, *gg = 0; size_t sz = strlen(name); - for (g = hashtab; *g; g++) { + for (g = ghashtab; *g; g++) { if (strncmp(name, (*g)->name, sz) == 0) { if ((*g)->name[sz] == 0) { gg = *g; @@ -618,7 +599,7 @@ int main(int argc, char *argv[]) gch = gethash(q); } if (!gch) - gch = hashtab[0]; + gch = gethash("md5"); xfree(q); } @@ -666,10 +647,10 @@ int main(int argc, char *argv[]) break; case 'l': { unsigned j; - for (j = 0; hashtab[j]; j++) { + for (j = 0; ghashtab[j]; j++) { if (j) fputc(' ', stdout); - printf("%s", hashtab[j]->name); + printf("%s", ghashtab[j]->name); } fputc('\n', stdout); exit(0); diff --git a/tests/gdsa b/tests/gdsa new file mode 100644 index 0000000..60a9f6f --- /dev/null +++ b/tests/gdsa @@ -0,0 +1,160 @@ +# $Id: gdsa,v 1.1 2004/04/04 19:42:59 mdw Exp $ +# +# Tests for abstract-group implementation of DSA + +sign { + # --- A simple and small test --- + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x1234 + "An example message" + 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640; + + # --- The FIPS186-1 test vector --- + + "prime { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, + 0xc773218c737ec8ee993b4f2ded30f48edace915f, + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + }" + sha + 0x2070b3223dba372fde1c0ffc7b2e3b498b260614 + "abc" + 0x358dad571462710f50e254cf1a376b2bdeaadfbf + 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 + 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8; + + # --- A test I made up --- + + "prime { + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + }" + sha + 0x23a252f60bae4907a8ed5b6203e2b1da32848cd9 + "A message signed with a 1024-bit DSA key." + 0x12ccb231683a3d9c13dca6fe882349537eebfd03 + 0x2a301061ac185440fbf595f8f7d894158b8d1897 + 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503; + + # --- Elliptic curve test vectors --- + + "ec { nist-b163 }" sha 0x1234 + "An example message" + 0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8 + 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 + 0x30e0d918fde3a33781f984b877f8501356b6fbae9; + + "ec { nist-p256 }" sha256 + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa + "An example message" + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c + 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 + 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a; +} + +verify { + # --- A simple and small test --- + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 + 0; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example messag" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df640 + -1; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0x5c085679fbfa9ee806781bdbd86a67dbf14df641 + -1; + + "prime { + 0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5, + 0x84d192cd06ae59691897fa409da6198d5269325d, + 0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e + }" + sha + 0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47 + "An example message" + 0x2718bf488b981992b164e664224dd00ca1ed4e1c + 0xe0d9e94702a8f8511f10161c7610816943b7289d + -1; + + # --- The FIPS186-1 test vector --- + + "prime { + 0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291, + 0xc773218c737ec8ee993b4f2ded30f48edace915f, + 0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802 + }" + sha + 0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333 + "abc" + 0x8bac1ab66410435cb7181f95b16ab97c92b341c0 + 0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8 + 0; + + # --- A test I made up --- + + "prime { + 0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7, + 0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9, + 0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014 + }" + sha + 0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074 + "A message signed with a 1024-bit DSA key." + 0x2a301061ac185440fbf595f8f7d894158b8d1897 + 0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503 + 0; + + # --- Elliptic curve test vectors --- + + "ec { nist-b163 }" sha + "0x1e7d847d0331a794852ded2b96c71d82e61f9bb4c, + 0x1a2370ab2e63f5aa8f348fbe83c0415a7d8ee207b" + "An example message" + 0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419 + 0x30e0d918fde3a33781f984b877f8501356b6fbae9 + 0; + + "ec { nist-p256 }" sha256 + "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40, + 0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611" + "An example message" + 0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6 + 0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a + 0; +} diff --git a/tests/gkcdsa b/tests/gkcdsa new file mode 100644 index 0000000..214947b --- /dev/null +++ b/tests/gkcdsa @@ -0,0 +1,59 @@ +# $Id: gkcdsa,v 1.1 2004/04/04 19:42:59 mdw Exp $ +# +# Tests for KCDSA + +sign { + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x068c4ef355d8b6f53eff1df6f243f98563896c58 + "This is a test message for KCDSA usage!" + 0x4b037e4b573bb7e334cad0a70bed6b5881df9e8e + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339; + + "ec { nist-p256 }" sha256 + 0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa + "Testing elliptic curves with KCDSA" + 0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c + e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 + 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617; +} + +verify { + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de + "This is a test message for KCDSA usage!" + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 + 0; + + "prime { + 0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f, + 0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb, + 0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639 + }" + has160 + 0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de + "This is a test message for KCDSA usage?" + 8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a + 0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339 + -1; + + "ec { nist-p256 }" sha256 + "0x5068f177ccebee933a27457707f6879eb5c4c59d58483766caf9aabcc367c0d1, + 0x4869c59dceadad93f1ed306b3ed544356c119996cc78708b9557c7ca5901da4a" + "Testing elliptic curves with KCDSA" + e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0 + 0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617 + 0; +} + diff --git a/tests/has160 b/tests/has160 new file mode 100644 index 0000000..ba3db65 --- /dev/null +++ b/tests/has160 @@ -0,0 +1,53 @@ +# Test vectors for HAS160 hash function +# +# $Id: has160,v 1.1 2004/04/04 19:42:59 mdw Exp $ + +# --- Basic hash function --- +# +# Test vectors from `The Revised Version of KCDSA' by Chae Hoon Lim. + +has160 { + "" 307964ef34151d37c8047adec7ab50f4ff89762d; + "a" 4872bcbc4cd0f0a9dc7c2f7045e5b43b6c830db8; + "abc" 975e810488cf2a3d49838478124afce4b1c78804; + "message digest" 2338dbc8638d31225f73086246ba529f96710bc6; + "abcdefghijklmnopqrstuvwxyz" 596185c9ab6703d0d0dbb98702bc0f5729cd1d3c; +} + +has160-rep { + "a" 1000000 d6ad6f0608b878da9b87999c2525cc84f4c9f18d; +} + +# --- HMAC mode --- +# +# Regression catching only. + +has160-hmac { + "Hi There" + 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + f5b44115a53f716b6f488de1098ee7c251418623; + + "what do ya want for nothing?" + 4a656665 + a74547c1ef0aa147c7428ab7e71664549be2a412; + + "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + e4c91bc71782fa44a56be1a34aae167e8ffc9734; + + "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ" + 0102030405060708090a0b0c0d0e0f10111213141516171819 + 14d1055da875222053bf1180bbef8892eba3ac30; + + "Test With Truncation" + 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + 124131a293f1fdf3d6b11e2b7f7a1f5b12e42d58; + + "Test Using Larger Than Block-Size Key - Hash Key First" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 63750d67af40e3fde33526545d300972a1527053; + + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + 1bdb821e399e208352c64f0655f6601e2a8a087c; +}