From 76d7dae26ab8b56dbafcec710fc42a5fb7d79840 Mon Sep 17 00:00:00 2001 From: knu Date: Fri, 13 Jul 2001 20:06:14 +0000 Subject: Import the "digest" module and the submodules, from the Rough Ruby project. ext/digest: This module provides the module Digest and the abstract class Digest::Base. ext/digest/md5 (which obsoletes ext/md5): This module provides the class Digest::MD5 which implements the MD5 Message-Digest Algorithm. ext/digest/rmd160: This module provides the class Digest::RMD160 which implements the RIPEMD-160 cryptographic hash function. ext/digest/sha1 (which obsoletes ext/sha1): This module provides the class Digest::SHA1 which implements the SHA-1 Secure Hash Algorithm. ext/digest/sha2: This module provides the classes Digest::SHA256, Digest::SHA384 and Digest::SHA512 which implement the SHA-256, SHA-384 and SHA-512 Secure Hash Algorithms, respectively. lib/md5.rb, lib/sha1.rb: These files are provided for backward compatibility. All these classes have the common API, which previously ext/md5 and ext/sha1 modules provided. While the new API keeps 100% backward compatibility, it has been enriched with several utility methods. Read digest.txt for further details. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1609 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/Setup | 7 +- ext/Setup.dj | 7 +- ext/Setup.emx | 7 +- ext/Setup.nt | 7 +- ext/Setup.x68 | 7 +- ext/digest/.cvsignore | 2 + ext/digest/MANIFEST | 11 + ext/digest/defs.h | 34 ++ ext/digest/digest.c | 331 +++++++++++++++ ext/digest/digest.h | 32 ++ ext/digest/digest.txt | 113 +++++ ext/digest/digest.txt.jp | 111 +++++ ext/digest/extconf.rb | 6 + ext/digest/lib/md5.rb | 14 + ext/digest/lib/sha1.rb | 14 + ext/digest/md5/.cvsignore | 2 + ext/digest/md5/MANIFEST | 4 + ext/digest/md5/extconf.rb | 19 + ext/digest/md5/md5.c | 432 +++++++++++++++++++ ext/digest/md5/md5.h | 75 ++++ ext/digest/md5/md5init.c | 34 ++ ext/digest/rmd160/.cvsignore | 2 + ext/digest/rmd160/MANIFEST | 5 + ext/digest/rmd160/extconf.rb | 20 + ext/digest/rmd160/rmd160.c | 464 ++++++++++++++++++++ ext/digest/rmd160/rmd160.h | 55 +++ ext/digest/rmd160/rmd160hl.c | 96 +++++ ext/digest/rmd160/rmd160init.c | 34 ++ ext/digest/sha1/.cvsignore | 2 + ext/digest/sha1/MANIFEST | 5 + ext/digest/sha1/extconf.rb | 20 + ext/digest/sha1/sha1.c | 283 +++++++++++++ ext/digest/sha1/sha1.h | 37 ++ ext/digest/sha1/sha1hl.c | 102 +++++ ext/digest/sha1/sha1init.c | 34 ++ ext/digest/sha2/.cvsignore | 2 + ext/digest/sha2/MANIFEST | 5 + ext/digest/sha2/extconf.rb | 20 + ext/digest/sha2/sha2.c | 937 +++++++++++++++++++++++++++++++++++++++++ ext/digest/sha2/sha2.h | 107 +++++ ext/digest/sha2/sha2hl.c | 252 +++++++++++ ext/digest/sha2/sha2init.c | 47 +++ ext/digest/test.rb | 100 +++++ ext/digest/test.sh | 27 ++ ext/md5/.cvsignore | 1 - ext/md5/MANIFEST | 8 - ext/md5/depend | 2 - ext/md5/extconf.rb | 3 - ext/md5/md5.h | 94 ----- ext/md5/md5.txt | 51 --- ext/md5/md5.txt.jp | 52 --- ext/md5/md5c.c | 410 ------------------ ext/md5/md5init.c | 123 ------ ext/sha1/.cvsignore | 1 - ext/sha1/MANIFEST | 7 - ext/sha1/extconf.rb | 3 - ext/sha1/sha1-ruby.c | 111 ----- ext/sha1/sha1.c | 172 -------- ext/sha1/sha1.h | 33 -- ext/sha1/sha1.txt | 56 --- ext/sha1/sha1.txt.jp | 56 --- 61 files changed, 3915 insertions(+), 1193 deletions(-) create mode 100644 ext/digest/.cvsignore create mode 100644 ext/digest/MANIFEST create mode 100644 ext/digest/defs.h create mode 100644 ext/digest/digest.c create mode 100644 ext/digest/digest.h create mode 100644 ext/digest/digest.txt create mode 100644 ext/digest/digest.txt.jp create mode 100644 ext/digest/extconf.rb create mode 100644 ext/digest/lib/md5.rb create mode 100644 ext/digest/lib/sha1.rb create mode 100644 ext/digest/md5/.cvsignore create mode 100644 ext/digest/md5/MANIFEST create mode 100644 ext/digest/md5/extconf.rb create mode 100644 ext/digest/md5/md5.c create mode 100644 ext/digest/md5/md5.h create mode 100644 ext/digest/md5/md5init.c create mode 100644 ext/digest/rmd160/.cvsignore create mode 100644 ext/digest/rmd160/MANIFEST create mode 100644 ext/digest/rmd160/extconf.rb create mode 100644 ext/digest/rmd160/rmd160.c create mode 100644 ext/digest/rmd160/rmd160.h create mode 100644 ext/digest/rmd160/rmd160hl.c create mode 100644 ext/digest/rmd160/rmd160init.c create mode 100644 ext/digest/sha1/.cvsignore create mode 100644 ext/digest/sha1/MANIFEST create mode 100644 ext/digest/sha1/extconf.rb create mode 100644 ext/digest/sha1/sha1.c create mode 100644 ext/digest/sha1/sha1.h create mode 100644 ext/digest/sha1/sha1hl.c create mode 100644 ext/digest/sha1/sha1init.c create mode 100644 ext/digest/sha2/.cvsignore create mode 100644 ext/digest/sha2/MANIFEST create mode 100644 ext/digest/sha2/extconf.rb create mode 100644 ext/digest/sha2/sha2.c create mode 100644 ext/digest/sha2/sha2.h create mode 100644 ext/digest/sha2/sha2hl.c create mode 100644 ext/digest/sha2/sha2init.c create mode 100644 ext/digest/test.rb create mode 100644 ext/digest/test.sh delete mode 100644 ext/md5/.cvsignore delete mode 100644 ext/md5/MANIFEST delete mode 100644 ext/md5/depend delete mode 100644 ext/md5/extconf.rb delete mode 100644 ext/md5/md5.h delete mode 100644 ext/md5/md5.txt delete mode 100644 ext/md5/md5.txt.jp delete mode 100644 ext/md5/md5c.c delete mode 100644 ext/md5/md5init.c delete mode 100644 ext/sha1/.cvsignore delete mode 100644 ext/sha1/MANIFEST delete mode 100644 ext/sha1/extconf.rb delete mode 100644 ext/sha1/sha1-ruby.c delete mode 100644 ext/sha1/sha1.c delete mode 100644 ext/sha1/sha1.h delete mode 100644 ext/sha1/sha1.txt delete mode 100644 ext/sha1/sha1.txt.jp (limited to 'ext') diff --git a/ext/Setup b/ext/Setup index 29bc72240d..cc412e8667 100644 --- a/ext/Setup +++ b/ext/Setup @@ -3,13 +3,16 @@ #GD #curses #dbm +#digest +#digest/md5 +#digest/rmd160 +#digest/sha1 +#digest/sha2 #etc #fcntl #kconv -#md5 #pty #sdbm -#sha1 #socket #tk #tcltklib diff --git a/ext/Setup.dj b/ext/Setup.dj index e61102a5b6..3c01afa747 100644 --- a/ext/Setup.dj +++ b/ext/Setup.dj @@ -3,14 +3,17 @@ option nodynamic #GD #curses dbm +digest +digest/md5 +digest/rmd160 +digest/sha1 +digest/sha2 gdbm #etc fcntl nkf marshal -md5 readline sdbm -sha1 #socket #tkutil diff --git a/ext/Setup.emx b/ext/Setup.emx index 1f83a95d21..c85f724d9f 100644 --- a/ext/Setup.emx +++ b/ext/Setup.emx @@ -3,15 +3,18 @@ option nodynamic #Win32API curses #dbm +digest +digest/md5 +digest/rmd160 +digest/sha1 +digest/sha2 etc fcntl #gdbm -md5 nkf #pty #readline #sdbm -sha1 socket #tcltklib #tk diff --git a/ext/Setup.nt b/ext/Setup.nt index 9aa72432d8..39b9030987 100644 --- a/ext/Setup.nt +++ b/ext/Setup.nt @@ -4,17 +4,20 @@ Win32API #curses #dbm +digest +digest/md5 +digest/rmd160 +digest/sha1 +digest/sha2 #etc fcntl #gdbm #gtk marshal -md5 nkf #pty #readline sdbm -sha1 socket #tcltklib #tk diff --git a/ext/Setup.x68 b/ext/Setup.x68 index 94d198b9f0..25e9544d76 100644 --- a/ext/Setup.x68 +++ b/ext/Setup.x68 @@ -3,11 +3,14 @@ option nodynamic #GD #curses dbm +digest +digest/md5 +digest/rmd160 +digest/sha1 +digest/sha2 #etc fcntl kconv marshal -md5 -sha1 #socket #tkutil diff --git a/ext/digest/.cvsignore b/ext/digest/.cvsignore new file mode 100644 index 0000000000..fc802ff1c2 --- /dev/null +++ b/ext/digest/.cvsignore @@ -0,0 +1,2 @@ +Makefile +mkmf.log diff --git a/ext/digest/MANIFEST b/ext/digest/MANIFEST new file mode 100644 index 0000000000..346f755cd5 --- /dev/null +++ b/ext/digest/MANIFEST @@ -0,0 +1,11 @@ +MANIFEST +defs.h +digest.c +digest.h +digest.txt +digest.txt.jp +extconf.rb +lib/md5.rb +lib/sha1.rb +test.rb +test.sh diff --git a/ext/digest/defs.h b/ext/digest/defs.h new file mode 100644 index 0000000000..47bf7d030a --- /dev/null +++ b/ext/digest/defs.h @@ -0,0 +1,34 @@ +/* -*- C -*- + * $Id$ + */ + +#ifndef DEFS_H +#define DEFS_H + +#include "ruby.h" +#include + +#if defined(HAVE_SYS_CDEFS_H) +# include +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +#if defined(HAVE_INTTYPES_H) +# include +#else + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; +# if SIZEOF_LONG == 8 + typedef unsigned long uint64_t; +# elif defined(__GNUC__) + typedef unsigned long long uint64_t; +# elif defined(_MSC_VER) + typedef unsigned _int64 uint64_t; +# else +# error What is a 64bit integer type on this system? +# endif +#endif + +#endif /* DEFS_H */ diff --git a/ext/digest/digest.c b/ext/digest/digest.c new file mode 100644 index 0000000000..f737d254ab --- /dev/null +++ b/ext/digest/digest.c @@ -0,0 +1,331 @@ +/************************************************ + + digest.c - + + $Author$ + created at: Fri May 25 08:57:27 JST 2001 + + Copyright (C) 1995-2001 Yukihiro Matsumoto + Copyright (C) 2001 Akinori MUSHA + + $RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $ + $Id$ + +************************************************/ + +/* + * This module provides an interface to the following hash algorithms: + * + * - the MD5 Message-Digest Algorithm by the RSA Data Security, + * Inc., described in RFC 1321 + * + * - the SHA-1 Secure Hash Algorithm by NIST (the US' National + * Institute of Standards and Technology), described in FIPS PUB + * 180-1. + * + * - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US' + * National Institute of Standards and Technology), described in + * FIPS PUB 180-2. + * + * - the RIPEMD-160 cryptographic hash function, designed by Hans + * Dobbertin, Antoon Bosselaers, and Bart Preneel. + */ + +#include "digest.h" + +static VALUE mDigest, cDigest_Base; +static ID id_metadata; + +/* + * Digest::Base + */ + +static algo_t * +get_digest_base_metadata(class) + VALUE class; +{ + VALUE obj; + algo_t *algo; + + if (rb_cvar_defined(class, id_metadata) == Qfalse) + rb_notimplement(); + + obj = rb_cvar_get(class, id_metadata); + + Data_Get_Struct(obj, algo_t, algo); + + return algo; +} + +static VALUE +rb_digest_base_s_new(argc, argv, class) + int argc; + VALUE* argv; + VALUE class; +{ + algo_t *algo; + VALUE obj; + void *pctx; + + if (class == cDigest_Base) + rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); + + algo = get_digest_base_metadata(class); + + pctx = xmalloc(algo->ctx_size); + algo->init_func(pctx); + + obj = Data_Wrap_Struct(class, 0, free, pctx); + + rb_obj_call_init(obj, argc, argv); + + return obj; +} + +static VALUE +rb_digest_base_s_digest(class, str) + VALUE class; + VALUE str; +{ + algo_t *algo; + void *pctx; + size_t len; + unsigned char *digest; + VALUE obj; + + if (class == cDigest_Base) + rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); + + algo = get_digest_base_metadata(class); + + pctx = xmalloc(algo->ctx_size); + algo->init_func(pctx); + algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len); + + len = algo->digest_len; + + digest = xmalloc(len); + algo->final_func(digest, pctx); + + obj = rb_str_new(digest, len); + + free(digest); + free(pctx); + + return obj; +} + +static VALUE +rb_digest_base_s_hexdigest(class, str) + VALUE class; + VALUE str; +{ + algo_t *algo; + void *pctx; + size_t len; + unsigned char *hexdigest; + VALUE obj; + + if (class == cDigest_Base) + rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); + + algo = get_digest_base_metadata(class); + + pctx = xmalloc(algo->ctx_size); + algo->init_func(pctx); + algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len); + + len = algo->digest_len * 2; + + hexdigest = xmalloc(len + 1); /* +1 is for '\0' */ + algo->end_func(pctx, hexdigest); + puts(hexdigest); + obj = rb_str_new(hexdigest, len); + + free(hexdigest); + free(pctx); + + return obj; +} + +static VALUE +rb_digest_base_clone(self) + VALUE self; +{ + algo_t *algo; + void *pctx1, *pctx2; + VALUE class; + + class = CLASS_OF(self); + algo = get_digest_base_metadata(class); + Data_Get_Struct(self, void, pctx1); + + pctx2 = xmalloc(algo->ctx_size); + memcpy(pctx2, pctx1, algo->ctx_size); + + return Data_Wrap_Struct(class, 0, free, pctx2); +} + +static VALUE +rb_digest_base_update(self, str) + VALUE self, str; +{ + algo_t *algo; + void *pctx; + +#ifdef StringValue + StringValue(str); +#else + Check_Type(str, T_STRING); +#endif + + algo = get_digest_base_metadata(CLASS_OF(self)); + Data_Get_Struct(self, void, pctx); + + algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len); + + return self; +} + +static VALUE +rb_digest_base_init(argc, argv, self) + int argc; + VALUE* argv; + VALUE self; +{ + VALUE arg; + + rb_scan_args(argc, argv, "01", &arg); + + if (!NIL_P(arg)) rb_digest_base_update(self, arg); + + return self; +} + +static VALUE +rb_digest_base_digest(self) + VALUE self; +{ + algo_t *algo; + void *pctx1, *pctx2; + unsigned char *digest; + size_t len; + VALUE str; + + algo = get_digest_base_metadata(CLASS_OF(self)); + Data_Get_Struct(self, void, pctx1); + + len = algo->ctx_size; + + pctx2 = xmalloc(len); + memcpy(pctx2, pctx1, len); + + len = algo->digest_len; + + digest = xmalloc(len); + algo->final_func(digest, pctx2); + + str = rb_str_new(digest, len); + + free(digest); + free(pctx2); + + return str; +} + +static VALUE +rb_digest_base_hexdigest(self) + VALUE self; +{ + algo_t *algo; + void *pctx1, *pctx2; + unsigned char *hexdigest; + size_t len; + VALUE str; + + algo = get_digest_base_metadata(CLASS_OF(self)); + Data_Get_Struct(self, void, pctx1); + + len = algo->ctx_size; + + pctx2 = xmalloc(len); + memcpy(pctx2, pctx1, len); + + len = algo->digest_len * 2; + + hexdigest = xmalloc(len + 1); /* +1 is for '\0' */ + algo->end_func(pctx2, hexdigest); + + str = rb_str_new(hexdigest, len); + + free(hexdigest); + free(pctx2); + + return str; +} + +static VALUE +rb_digest_base_equal(self, other) + VALUE self, other; +{ + algo_t *algo; + VALUE class; + VALUE str1, str2; + + class = CLASS_OF(self); + algo = get_digest_base_metadata(class); + + if (CLASS_OF(other) == class) { + void *pctx1, *pctx2; + + Data_Get_Struct(self, void, pctx1); + Data_Get_Struct(other, void, pctx2); + + return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse; + } + +#ifdef StringValue + StringValue(other); +#else + Check_Type(other, T_STRING); +#endif + str2 = other; + + if (RSTRING(str2)->len == algo->digest_len) + str1 = rb_digest_base_digest(self); + else + str1 = rb_digest_base_hexdigest(self); + + if (RSTRING(str1)->len == RSTRING(str2)->len + && rb_str_cmp(str1, str2) == 0) + return Qtrue; + + return Qfalse; +} + +/* + * Init + */ + +void +Init_digest() +{ + mDigest = rb_define_module("Digest"); + + cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject); + + rb_define_singleton_method(cDigest_Base, "new", rb_digest_base_s_new, -1); + rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1); + rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1); + + rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1); + rb_define_method(cDigest_Base, "clone", rb_digest_base_clone, 0); + rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1); + rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1); + rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0); + rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0); + rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0); + rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1); + + id_metadata = rb_intern("metadata"); +} diff --git a/ext/digest/digest.h b/ext/digest/digest.h new file mode 100644 index 0000000000..5e846df040 --- /dev/null +++ b/ext/digest/digest.h @@ -0,0 +1,32 @@ +/************************************************ + + digest.c - + + $Author$ + created at: Fri May 25 08:54:56 JST 2001 + + + Copyright (C) 2001 Akinori MUSHA + + $RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $ + $Id$ + +************************************************/ + +#include "ruby.h" + +typedef void (*hash_init_func_t) _((void *)); +typedef void (*hash_update_func_t) _((void *, unsigned char *, size_t)); +typedef void (*hash_end_func_t) _((void *, unsigned char *)); +typedef void (*hash_final_func_t) _((unsigned char *, void *)); +typedef int (*hash_equal_func_t) _((void *, void *)); + +typedef struct { + size_t digest_len; + size_t ctx_size; + hash_init_func_t init_func; + hash_update_func_t update_func; + hash_end_func_t end_func; + hash_final_func_t final_func; + hash_equal_func_t equal_func; +} algo_t; diff --git a/ext/digest/digest.txt b/ext/digest/digest.txt new file mode 100644 index 0000000000..5797dd18f9 --- /dev/null +++ b/ext/digest/digest.txt @@ -0,0 +1,113 @@ +.\" digest.txt - -*- Indented-Text -*- created at: Fri May 25 08:13:50 JST 2001 +$RoughId: digest.txt,v 1.9 2001/07/13 19:46:51 knu Exp $ +$Id$ + +** MD5(Class) + +A class to implement the MD5 Message-Digest Algorithm by RSA Data +Security, Inc., described in RFC1321. + +Superclass: Digest::Base + +require 'digest/md5' + +** SHA1(Class) + +A class to implement the SHA-1 Secure Hash Algorithm by NIST (the US' +National Institute of Standards and Technology), described in FIPS PUB +180-1. + +Superclass: Digest::Base + +require 'digest/sha1' + +** SHA256(Class) +** SHA384(Class) +** SHA512(Class) + +Classes to implement the SHA-256/384/512 Secure Hash Algorithm(s) by +NIST (the US' National Institute of Standards and Technology), +described in FIPS PUB 180-2. + +Superclass: Digest::Base + +require 'digest/sha2' + +** RMD160(Class) + +A class to implement the RIPEMD-160 cryptographic hash function, +designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. + +Superclass: Digest::Base + +require 'digest/rmd160' + + +Those above classes provide a common interface as shown below. + + +Class Methods: + + new([str]) + + Creates a new digest object. If a string argument is given, + it is added to the object. (see update.) + + digest(str) + + Immediately calculates and return the hash of the given + strings as a string. Equivalent to new(str).digest. + + hexdigest(str) + + Immediately calculates and return the hash of the given + strings as a string of hexadecimal digits. Equivalent to + new(str).hexdigest. + +Methods: + + clone + + Creates a copy of the digest object. + + digest + + Returns the hash of the added strings as a string of 16 bytes + for MD5, 20 bytes for SHA1 and RMD160, 32 bytes for SHA256, 48 + bytes for SHA384, and 64 bytes for SHA512. + + hexdigest + to_s + + Returns the hash of the added strings as a string of 32 + hexadecimal digits for MD5, 40 hexadecimal digits for SHA1 and + RMD160, 64 hexadecimal digits for SHA256, 96 hexadecimal + digits for SHA384, and 128 hexadecimal digits for SHA512. + This method is equal to: + + def hexdigest + digest.unpack("H*")[0] + end + + update(str) + << str + + Appends the string str to the digest object. Repeated calls + are equivalent to a single call with the concatenation of all + the arguments, i.e. m.update(a); m.update(b) is equivalent to + m.update(a + b) and m << a << b is equivalent to m << a + b. + + == md + + Checks if the object is equal to the given digest object. + + == str + + Regards the value as either a digest value or a hexdigest + value (depending on the length) and checks if the object is + equal to the given string. + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/digest/digest.txt.jp b/ext/digest/digest.txt.jp new file mode 100644 index 0000000000..6fad4deb33 --- /dev/null +++ b/ext/digest/digest.txt.jp @@ -0,0 +1,111 @@ +.\" digest.txt.jp - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001 +$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $ +$Id$ + +** MD5(クラス) + +RFC1321に記述されているRSA Data Security, Inc. の MD5 Message-Digest +Algorithmを実装するクラス。 + +Superclass: Digest::Base + +require 'digest/md5' + +** SHA1(クラス) + +FIPS PUB 180-1に記述されているNIST (the US' National Institute of +Standards and Technology) の SHA-1 Secure Hash Algorithmを実装するクラス。 + +Superclass: Digest::Base + +require 'digest/sha1' + +** SHA256(クラス) +** SHA384(クラス) +** SHA512(クラス) + +FIPS PUB 180-2に記述されているNIST (the US' National Institute of +Standards and Technology) の SHA-256/384/512 Secure Hash Algorithmを +実装するクラス。 + +Superclass: Digest::Base + +require 'digest/sha2' + +** RMD160(クラス) + +Hans Dobbertin, Antoon Bosselaers, Bart Preneel によって設計された +RIPEMD-160 ハッシュ関数を実装するクラス。 + +Superclass: Digest::Base + +require 'digest/rmd160' + + +これらのクラスは以下のような共通のインターフェースを提供する。 + + +Class Methods: + + new([str]) + + 新しいダイジェストオブジェクトを生成する.文字列引数が与えられる + とそれを追加する(see update)。 + + digest(str) + + 与えられた文字列に対するハッシュ値を文字列で返す。 + new(str).digest と等価。 + + hexdigest(str) + + 与えられた文字列に対するハッシュ値を、ASCIIコードを使って + 16進数の列を示す文字列にエンコードして返す。 + new(str).hexdigest と等価。 + +Methods: + + clone + + ダイジェストオブジェクトの複製を作る。 + + digest + + 今までに追加した文字列に対するハッシュ値を文字列で返す。MD5では + 16バイト長、SHA1およびRMD160では20バイト長、SHA256では32バイト長、 + SHA384では48バイト長、SHA512では64バイト長となる。 + + hexdigest + to_s + + 今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って + 16進数の列を示す文字列にエンコードして返す。MD5では32バイト長、 + SHA1およびRMD160では40バイト長、SHA256では64バイト長、SHA384では + 96バイト長、SHA512では128バイト長となる。Rubyで書くと以下と同じ。 + + def hexdigest + digest.unpack("H*")[0] + end + + update(str) + << str + + 文字列を追加する。複数回updateを呼ぶことは文字列を連結して + updateを呼ぶことと等しい。すなわち m.update(a); m.update(b) は + m.update(a + b) と、 m << a << b は m << a + b とそれぞれ等価 + である。 + + == md + + 与えられたダイジェストオブジェクトと比較する。 + + == str + + 与えられた文字列を digest 値、もしくは hexdigest 値と比較する。 + いずれの値と見るかは与えられた文字列の長さによって自動判別 + される。 + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/digest/extconf.rb b/ext/digest/extconf.rb new file mode 100644 index 0000000000..cd512622a4 --- /dev/null +++ b/ext/digest/extconf.rb @@ -0,0 +1,6 @@ +# $RoughId: extconf.rb,v 1.6 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require "mkmf" + +create_makefile("digest") diff --git a/ext/digest/lib/md5.rb b/ext/digest/lib/md5.rb new file mode 100644 index 0000000000..1d05d7d04e --- /dev/null +++ b/ext/digest/lib/md5.rb @@ -0,0 +1,14 @@ +# just for compatibility; requiring "md5" is obsoleted +# +# $RoughId: md5.rb,v 1.4 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require 'digest/md5' + +MD5 = Digest::MD5 + +class MD5 + def self.md5(*args) + new(*args) + end +end diff --git a/ext/digest/lib/sha1.rb b/ext/digest/lib/sha1.rb new file mode 100644 index 0000000000..c4ac6f66ea --- /dev/null +++ b/ext/digest/lib/sha1.rb @@ -0,0 +1,14 @@ +# just for compatibility; requiring "sha1" is obsoleted +# +# $RoughId: sha1.rb,v 1.4 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require 'digest/sha1' + +SHA1 = Digest::SHA1 + +class SHA1 + def self.sha1(*args) + new(*args) + end +end diff --git a/ext/digest/md5/.cvsignore b/ext/digest/md5/.cvsignore new file mode 100644 index 0000000000..fc802ff1c2 --- /dev/null +++ b/ext/digest/md5/.cvsignore @@ -0,0 +1,2 @@ +Makefile +mkmf.log diff --git a/ext/digest/md5/MANIFEST b/ext/digest/md5/MANIFEST new file mode 100644 index 0000000000..1b8a861b6b --- /dev/null +++ b/ext/digest/md5/MANIFEST @@ -0,0 +1,4 @@ +extconf.rb +md5.c +md5.h +md5init.c diff --git a/ext/digest/md5/extconf.rb b/ext/digest/md5/extconf.rb new file mode 100644 index 0000000000..cbf1e1b60f --- /dev/null +++ b/ext/digest/md5/extconf.rb @@ -0,0 +1,19 @@ +# $RoughId: extconf.rb,v 1.1 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require "mkmf" + +$CFLAGS << " -DHAVE_CONFIG_H -I.." + +$objs = [ + "md5.#{$OBJEXT}", + "md5init.#{$OBJEXT}", +] + +have_header("sys/cdefs.h") + +have_header("inttypes.h") + +have_header("unistd.h") + +create_makefile("digest/md5") diff --git a/ext/digest/md5/md5.c b/ext/digest/md5/md5.c new file mode 100644 index 0000000000..6b61f031c4 --- /dev/null +++ b/ext/digest/md5/md5.c @@ -0,0 +1,432 @@ +/* + Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ + +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; + made test program self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +/*$OrigId: md5c.c,v 1.2 2001/03/26 08:57:14 matz Exp $ */ +/*$RoughId: md5.c,v 1.2 2001/07/13 19:48:41 knu Exp $ */ +/*$Id$ */ + +#include "md5.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7*2] = { + "", "d41d8cd98f00b204e9800998ecf8427e", + "a", "0cc175b9c0f1b6a831c399e269772661", + "abc", "900150983cd24fb0d6963f7d28e17f72", + "message digest", "f96b697d7cb7938d525a2f31aaf161d0", + "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" + }; + int i; + + for (i = 0; i < 7*2; i += 2) { + MD5_CTX state; + uint8_t digest[16]; + char hex_output[16*2 + 1]; + int di; + + MD5_Init(&state); + MD5_Update(&state, (const uint8_t *)test[i], strlen(test[i])); + MD5_Final(digest, &state); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + sprintf(hex_output + di * 2, "%02x", digest[di]); + puts(hex_output); + if (strcmp(hex_output, test[i + 1])) + printf("**** ERROR, should be: %s\n", test[i + 1]); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#ifdef COMPUTE_T_VALUES +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + + /* + * The following nonsense is only to avoid compiler warnings about + * "integer constant is unsigned in ANSI C, signed with -traditional". + */ + if (v >> 31) { + printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i, + v, (unsigned long)(unsigned int)(~v)); + } else { + printf("#define T%d 0x%08lx\n", i, v); + } + } + return 0; +} +#endif /* COMPUTE_T_VALUES */ +/* + * End of T computation program. + */ +#ifdef T_MASK +#undef T_MASK +#endif +#define T_MASK ((uint32_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static void +md5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/) +{ + uint32_t + a = pms->state[0], b = pms->state[1], + c = pms->state[2], d = pms->state[3]; + uint32_t t; + +#ifdef WORDS_BIGENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + uint32_t X[16]; + const uint8_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + uint32_t xbuf[16]; + const uint32_t *X; + + if (!((data - (const uint8_t *)0) & 3)) { + /* data are properly aligned */ + X = (const uint32_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->state[0] += a; + pms->state[1] += b; + pms->state[2] += c; + pms->state[3] += d; +} + +void +MD5_Init(MD5_CTX *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->state[0] = 0x67452301; + pms->state[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->state[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->state[3] = 0x10325476; +} + +void +MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes) +{ + const uint8_t *p = data; + size_t left = nbytes; + size_t offset = (pms->count[0] >> 3) & 63; + uint32_t nbits = (uint32_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buffer + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buffer); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buffer, p, left); +} + +void +MD5_Final(uint8_t *digest, MD5_CTX *pms) +{ + static const uint8_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + uint8_t data[8]; + size_t i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (uint8_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + MD5_Update(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + MD5_Update(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (uint8_t)(pms->state[i >> 2] >> ((i & 3) << 3)); +} + +void +MD5_End(MD5_CTX *pctx, uint8_t *hexdigest) +{ + unsigned char digest[16]; + size_t i; + + MD5_Final(digest, pctx); + + for (i = 0; i < 16; i++) + sprintf(hexdigest + i * 2, "%02x", digest[i]); +} + +int MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) { + return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0 + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0; +} diff --git a/ext/digest/md5/md5.h b/ext/digest/md5/md5.h new file mode 100644 index 0000000000..4b1f00b3ec --- /dev/null +++ b/ext/digest/md5/md5.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +/* $OrigId: md5.h,v 1.2 2001/03/26 08:57:14 matz Exp $ */ +/* $RoughId: md5.h,v 1.2 2001/07/13 19:48:41 knu Exp $ */ +/* $Id$ */ + +#ifndef MD5_INCLUDED +# define MD5_INCLUDED + +#include "defs.h" + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3. + */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + uint32_t count[2]; /* message length in bits, lsw first */ + uint32_t state[4]; /* digest buffer */ + uint8_t buffer[64]; /* accumulate block */ +} MD5_CTX; + +void MD5_Init _((MD5_CTX *pms)); +void MD5_Update _((MD5_CTX *pms, const uint8_t *data, size_t nbytes)); +void MD5_Final _((uint8_t *digest, MD5_CTX *pms)); +void MD5_End _((MD5_CTX *pctx, uint8_t *hexdigest)); +int MD5_Equal _((MD5_CTX *pctx1, MD5_CTX *pctx2)); + +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 +#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +#endif /* MD5_INCLUDED */ diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c new file mode 100644 index 0000000000..0f5b9b3543 --- /dev/null +++ b/ext/digest/md5/md5init.c @@ -0,0 +1,34 @@ +/* $RoughId: md5init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +#include "digest.h" +#include "md5.h" + +static algo_t md5 = { + MD5_DIGEST_LENGTH, + sizeof(MD5_CTX), + (hash_init_func_t)MD5_Init, + (hash_update_func_t)MD5_Update, + (hash_end_func_t)MD5_End, + (hash_final_func_t)MD5_Final, + (hash_equal_func_t)MD5_Equal, +}; + +void +Init_md5() +{ + VALUE mDigest, cDigest_Base, cDigest_MD5; + ID id_metadata; + + rb_require("digest.so"); + + mDigest = rb_path2class("Digest"); + cDigest_Base = rb_path2class("Digest::Base"); + + cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); + + id_metadata = rb_intern("metadata"); + + rb_cvar_declare(cDigest_MD5, id_metadata, + Data_Wrap_Struct(rb_cObject, 0, 0, &md5)); +} diff --git a/ext/digest/rmd160/.cvsignore b/ext/digest/rmd160/.cvsignore new file mode 100644 index 0000000000..fc802ff1c2 --- /dev/null +++ b/ext/digest/rmd160/.cvsignore @@ -0,0 +1,2 @@ +Makefile +mkmf.log diff --git a/ext/digest/rmd160/MANIFEST b/ext/digest/rmd160/MANIFEST new file mode 100644 index 0000000000..ff16164ca7 --- /dev/null +++ b/ext/digest/rmd160/MANIFEST @@ -0,0 +1,5 @@ +extconf.rb +rmd160.c +rmd160.h +rmd160hl.c +rmd160init.c diff --git a/ext/digest/rmd160/extconf.rb b/ext/digest/rmd160/extconf.rb new file mode 100644 index 0000000000..708e6e40f7 --- /dev/null +++ b/ext/digest/rmd160/extconf.rb @@ -0,0 +1,20 @@ +# $RoughId: extconf.rb,v 1.1 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require "mkmf" + +$CFLAGS << " -DHAVE_CONFIG_H -I.." + +$objs = [ + "rmd160.#{$OBJEXT}", + "rmd160hl.#{$OBJEXT}", + "rmd160init.#{$OBJEXT}", +] + +have_header("sys/cdefs.h") + +have_header("inttypes.h") + +have_header("unistd.h") + +create_makefile("digest/rmd160") diff --git a/ext/digest/rmd160/rmd160.c b/ext/digest/rmd160/rmd160.c new file mode 100644 index 0000000000..2de3c99b29 --- /dev/null +++ b/ext/digest/rmd160/rmd160.c @@ -0,0 +1,464 @@ +/* $NetBSD: rmd160.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */ +/* $RoughId: rmd160.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/********************************************************************\ + * + * FILE: rmd160.c + * + * CONTENTS: A sample C-implementation of the RIPEMD-160 + * hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * (Arranged for libc by Todd C. Miller) + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * +\********************************************************************/ + +#include "rmd160.h" + +#ifndef lint +/* __RCSID("$NetBSD: rmd160.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */ +#endif /* not lint */ + +/* header files */ + +#ifdef HAVE_SYS_ENDIAN_H_ +#include +#endif + +#ifdef HAVE_MACHINE_ENDIAN_H_ +#include +#endif + +/* #include "namespace.h" */ + +#include +#include +#include +#include + +#ifndef _DIAGASSERT +#define _DIAGASSERT(cond) assert(cond) +#endif + + +/********************************************************************/ + +/* macro definitions */ + +/* collect four bytes into one word: */ +#define BYTES_TO_DWORD(strptr) \ + (((uint32_t) *((strptr)+3) << 24) | \ + ((uint32_t) *((strptr)+2) << 16) | \ + ((uint32_t) *((strptr)+1) << 8) | \ + ((uint32_t) *(strptr))) + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the three basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) { \ + (a) += F((b), (c), (d)) + (x); \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define GG(a, b, c, d, e, x, s) { \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define HH(a, b, c, d, e, x, s) { \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define II(a, b, c, d, e, x, s) { \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define JJ(a, b, c, d, e, x, s) { \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define FFF(a, b, c, d, e, x, s) { \ + (a) += F((b), (c), (d)) + (x); \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define GGG(a, b, c, d, e, x, s) { \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define HHH(a, b, c, d, e, x, s) { \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define III(a, b, c, d, e, x, s) { \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} +#define JJJ(a, b, c, d, e, x, s) { \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6U; \ + (a) = ROL((a), (s)) + (e); \ + (c) = ROL((c), 10); \ +} + +/********************************************************************/ + +void +RMD160_Init(RMD160_CTX *context) +{ + + _DIAGASSERT(context != NULL); + + /* ripemd-160 initialization constants */ + context->state[0] = 0x67452301U; + context->state[1] = 0xefcdab89U; + context->state[2] = 0x98badcfeU; + context->state[3] = 0x10325476U; + context->state[4] = 0xc3d2e1f0U; + context->length[0] = context->length[1] = 0; + context->buflen = 0; +} + +/********************************************************************/ + +void +RMD160_Transform(uint32_t state[5], const uint32_t block[16]) +{ + uint32_t aa, bb, cc, dd, ee; + uint32_t aaa, bbb, ccc, ddd, eee; + + _DIAGASSERT(state != NULL); + _DIAGASSERT(block != NULL); + + aa = aaa = state[0]; + bb = bbb = state[1]; + cc = ccc = state[2]; + dd = ddd = state[3]; + ee = eee = state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, block[ 0], 11); + FF(ee, aa, bb, cc, dd, block[ 1], 14); + FF(dd, ee, aa, bb, cc, block[ 2], 15); + FF(cc, dd, ee, aa, bb, block[ 3], 12); + FF(bb, cc, dd, ee, aa, block[ 4], 5); + FF(aa, bb, cc, dd, ee, block[ 5], 8); + FF(ee, aa, bb, cc, dd, block[ 6], 7); + FF(dd, ee, aa, bb, cc, block[ 7], 9); + FF(cc, dd, ee, aa, bb, block[ 8], 11); + FF(bb, cc, dd, ee, aa, block[ 9], 13); + FF(aa, bb, cc, dd, ee, block[10], 14); + FF(ee, aa, bb, cc, dd, block[11], 15); + FF(dd, ee, aa, bb, cc, block[12], 6); + FF(cc, dd, ee, aa, bb, block[13], 7); + FF(bb, cc, dd, ee, aa, block[14], 9); + FF(aa, bb, cc, dd, ee, block[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, block[ 7], 7); + GG(dd, ee, aa, bb, cc, block[ 4], 6); + GG(cc, dd, ee, aa, bb, block[13], 8); + GG(bb, cc, dd, ee, aa, block[ 1], 13); + GG(aa, bb, cc, dd, ee, block[10], 11); + GG(ee, aa, bb, cc, dd, block[ 6], 9); + GG(dd, ee, aa, bb, cc, block[15], 7); + GG(cc, dd, ee, aa, bb, block[ 3], 15); + GG(bb, cc, dd, ee, aa, block[12], 7); + GG(aa, bb, cc, dd, ee, block[ 0], 12); + GG(ee, aa, bb, cc, dd, block[ 9], 15); + GG(dd, ee, aa, bb, cc, block[ 5], 9); + GG(cc, dd, ee, aa, bb, block[ 2], 11); + GG(bb, cc, dd, ee, aa, block[14], 7); + GG(aa, bb, cc, dd, ee, block[11], 13); + GG(ee, aa, bb, cc, dd, block[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, block[ 3], 11); + HH(cc, dd, ee, aa, bb, block[10], 13); + HH(bb, cc, dd, ee, aa, block[14], 6); + HH(aa, bb, cc, dd, ee, block[ 4], 7); + HH(ee, aa, bb, cc, dd, block[ 9], 14); + HH(dd, ee, aa, bb, cc, block[15], 9); + HH(cc, dd, ee, aa, bb, block[ 8], 13); + HH(bb, cc, dd, ee, aa, block[ 1], 15); + HH(aa, bb, cc, dd, ee, block[ 2], 14); + HH(ee, aa, bb, cc, dd, block[ 7], 8); + HH(dd, ee, aa, bb, cc, block[ 0], 13); + HH(cc, dd, ee, aa, bb, block[ 6], 6); + HH(bb, cc, dd, ee, aa, block[13], 5); + HH(aa, bb, cc, dd, ee, block[11], 12); + HH(ee, aa, bb, cc, dd, block[ 5], 7); + HH(dd, ee, aa, bb, cc, block[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, block[ 1], 11); + II(bb, cc, dd, ee, aa, block[ 9], 12); + II(aa, bb, cc, dd, ee, block[11], 14); + II(ee, aa, bb, cc, dd, block[10], 15); + II(dd, ee, aa, bb, cc, block[ 0], 14); + II(cc, dd, ee, aa, bb, block[ 8], 15); + II(bb, cc, dd, ee, aa, block[12], 9); + II(aa, bb, cc, dd, ee, block[ 4], 8); + II(ee, aa, bb, cc, dd, block[13], 9); + II(dd, ee, aa, bb, cc, block[ 3], 14); + II(cc, dd, ee, aa, bb, block[ 7], 5); + II(bb, cc, dd, ee, aa, block[15], 6); + II(aa, bb, cc, dd, ee, block[14], 8); + II(ee, aa, bb, cc, dd, block[ 5], 6); + II(dd, ee, aa, bb, cc, block[ 6], 5); + II(cc, dd, ee, aa, bb, block[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, block[ 4], 9); + JJ(aa, bb, cc, dd, ee, block[ 0], 15); + JJ(ee, aa, bb, cc, dd, block[ 5], 5); + JJ(dd, ee, aa, bb, cc, block[ 9], 11); + JJ(cc, dd, ee, aa, bb, block[ 7], 6); + JJ(bb, cc, dd, ee, aa, block[12], 8); + JJ(aa, bb, cc, dd, ee, block[ 2], 13); + JJ(ee, aa, bb, cc, dd, block[10], 12); + JJ(dd, ee, aa, bb, cc, block[14], 5); + JJ(cc, dd, ee, aa, bb, block[ 1], 12); + JJ(bb, cc, dd, ee, aa, block[ 3], 13); + JJ(aa, bb, cc, dd, ee, block[ 8], 14); + JJ(ee, aa, bb, cc, dd, block[11], 11); + JJ(dd, ee, aa, bb, cc, block[ 6], 8); + JJ(cc, dd, ee, aa, bb, block[15], 5); + JJ(bb, cc, dd, ee, aa, block[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, block[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, block[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, block[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, block[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, block[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, block[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, block[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, block[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, block[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, block[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, block[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, block[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, block[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, block[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, block[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, block[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, block[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, block[11], 13); + III(ccc, ddd, eee, aaa, bbb, block[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, block[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, block[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, block[13], 8); + III(ddd, eee, aaa, bbb, ccc, block[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, block[10], 11); + III(bbb, ccc, ddd, eee, aaa, block[14], 7); + III(aaa, bbb, ccc, ddd, eee, block[15], 7); + III(eee, aaa, bbb, ccc, ddd, block[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, block[12], 7); + III(ccc, ddd, eee, aaa, bbb, block[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, block[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, block[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, block[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, block[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, block[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, block[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, block[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, block[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, block[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, block[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, block[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, block[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, block[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, block[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, block[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, block[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, block[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, block[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, block[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, block[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, block[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, block[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, block[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, block[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, block[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, block[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, block[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, block[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, block[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, block[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, block[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, block[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, block[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, block[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, block[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, block[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, block[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, block[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, block[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, block[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, block[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, block[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, block[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, block[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, block[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, block[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, block[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, block[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, block[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, block[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, block[11] , 11); + + /* combine results */ + ddd += cc + state[1]; /* final result for state[0] */ + state[1] = state[2] + dd + eee; + state[2] = state[3] + ee + aaa; + state[3] = state[4] + aa + bbb; + state[4] = state[0] + bb + ccc; + state[0] = ddd; +} + +/********************************************************************/ + +void +RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes) +{ + uint32_t X[16]; + uint32_t ofs = 0; + uint32_t i; +#ifdef WORDS_BIGENDIAN + uint32_t j; +#endif + + _DIAGASSERT(context != NULL); + _DIAGASSERT(data != NULL); + + /* update length[] */ + if (context->length[0] + nbytes < context->length[0]) + context->length[1]++; /* overflow to msb of length */ + context->length[0] += nbytes; + + (void)memset(X, 0, sizeof(X)); + + if ( context->buflen + nbytes < 64 ) + { + (void)memcpy(context->bbuffer + context->buflen, data, nbytes); + context->buflen += nbytes; + } + else + { + /* process first block */ + ofs = 64 - context->buflen; + (void)memcpy(context->bbuffer + context->buflen, data, ofs); +#ifndef WORDS_BIGENDIAN + (void)memcpy(X, context->bbuffer, sizeof(X)); +#else + for (j=0; j < 16; j++) + X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); +#endif + RMD160_Transform(context->state, X); + nbytes -= ofs; + + /* process remaining complete blocks */ + for (i = 0; i < (nbytes >> 6); i++) { +#ifndef WORDS_BIGENDIAN + (void)memcpy(X, data + (64 * i) + ofs, sizeof(X)); +#else + for (j=0; j < 16; j++) + X[j] = BYTES_TO_DWORD(data + (64 * i) + (4 * j) + ofs); +#endif + RMD160_Transform(context->state, X); + } + + /* + * Put last bytes from data into context's buffer + */ + context->buflen = nbytes & 63; + memcpy(context->bbuffer, data + (64 * i) + ofs, context->buflen); + } +} + +/********************************************************************/ + +void +RMD160_Final(uint8_t digest[20], RMD160_CTX *context) +{ + uint32_t i; + uint32_t X[16]; +#ifdef WORDS_BIGENDIAN + uint32_t j; +#endif + + _DIAGASSERT(digest != NULL); + _DIAGASSERT(context != NULL); + + /* append the bit m_n == 1 */ + context->bbuffer[context->buflen] = (uint8_t)'\200'; + + (void)memset(context->bbuffer + context->buflen + 1, 0, + 63 - context->buflen); +#ifndef WORDS_BIGENDIAN + (void)memcpy(X, context->bbuffer, sizeof(X)); +#else + for (j=0; j < 16; j++) + X[j] = BYTES_TO_DWORD(context->bbuffer + (4 * j)); +#endif + if ((context->buflen) > 55) { + /* length goes to next block */ + RMD160_Transform(context->state, X); + (void)memset(X, 0, sizeof(X)); + } + + /* append length in bits */ + X[14] = context->length[0] << 3; + X[15] = (context->length[0] >> 29) | + (context->length[1] << 3); + RMD160_Transform(context->state, X); + + if (digest != NULL) { + for (i = 0; i < 20; i += 4) { + /* extracts the 8 least significant bits. */ + digest[i] = context->state[i>>2]; + digest[i + 1] = (context->state[i>>2] >> 8); + digest[i + 2] = (context->state[i>>2] >> 16); + digest[i + 3] = (context->state[i>>2] >> 24); + } + } +} + +int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) { + return pctx1->buflen == pctx2->buflen + && memcmp(pctx1->length, pctx2->length, sizeof(pctx1->length)) == 0 + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->bbuffer, pctx2->bbuffer, sizeof(pctx1->bbuffer)) == 0; +} + +/************************ end of file rmd160.c **********************/ diff --git a/ext/digest/rmd160/rmd160.h b/ext/digest/rmd160/rmd160.h new file mode 100644 index 0000000000..53c1e0c1e0 --- /dev/null +++ b/ext/digest/rmd160/rmd160.h @@ -0,0 +1,55 @@ +/* $NetBSD: rmd160.h,v 1.2 2000/07/07 10:47:06 ad Exp $ */ +/* $RoughId: rmd160.h,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/********************************************************************\ + * + * FILE: rmd160.h + * + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * +\********************************************************************/ + +/* + * from OpenBSD: rmd160.h,v 1.4 1999/08/16 09:59:04 millert Exp + */ + +#ifndef _RMD160_H_ +#define _RMD160_H_ + +#include "defs.h" + +typedef struct { + uint32_t state[5]; /* state (ABCDE) */ + uint32_t length[2]; /* number of bits */ + uint8_t bbuffer[64]; /* overflow buffer */ + uint32_t buflen; /* number of chars in bbuffer */ +} RMD160_CTX; + +__BEGIN_DECLS +void RMD160_Init _((RMD160_CTX *)); +void RMD160_Transform _((uint32_t[5], const uint32_t[16])); +void RMD160_Update _((RMD160_CTX *, const uint8_t *, size_t)); +void RMD160_Final _((uint8_t[20], RMD160_CTX *)); +int RMD160_Equal _((RMD160_CTX *, RMD160_CTX *)); +#ifndef _KERNEL +char *RMD160_End _((RMD160_CTX *, char *)); +char *RMD160_File _((char *, char *)); +char *RMD160_Data _((const uint8_t *, size_t, char *)); +#endif /* _KERNEL */ +__END_DECLS + +#define RMD160_BLOCK_LENGTH 64 +#define RMD160_DIGEST_LENGTH 20 +#define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1) + +#endif /* !_RMD160_H_ */ diff --git a/ext/digest/rmd160/rmd160hl.c b/ext/digest/rmd160/rmd160hl.c new file mode 100644 index 0000000000..4c5e0217d9 --- /dev/null +++ b/ext/digest/rmd160/rmd160hl.c @@ -0,0 +1,96 @@ +/* $NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */ +/* $RoughId: rmd160hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/* rmd160hl.c + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * from OpenBSD: rmd160hl.c,v 1.2 1999/08/17 09:13:12 millert Exp $ + */ + +#include "rmd160.h" + +#ifndef lint +/* __RCSID("$NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */ +#endif /* not lint */ + +/* #include "namespace.h" */ + +#include +#include +#include +#include +#include +#if defined(HAVE_UNISTD_H) +# include +#endif + +#ifndef _DIAGASSERT +#define _DIAGASSERT(cond) assert(cond) +#endif + + +char * +RMD160_End(RMD160_CTX *ctx, char *buf) +{ + size_t i; + char *p = buf; + uint8_t digest[20]; + static const char hex[]="0123456789abcdef"; + + _DIAGASSERT(ctx != NULL); + /* buf may be NULL */ + + if (p == NULL && (p = malloc(41)) == NULL) + return 0; + + RMD160_Final(digest,ctx); + for (i = 0; i < 20; i++) { + p[i + i] = hex[(uint32_t)digest[i] >> 4]; + p[i + i + 1] = hex[digest[i] & 0x0f]; + } + p[i + i] = '\0'; + return(p); +} + +char * +RMD160_File(char *filename, char *buf) +{ + uint8_t buffer[BUFSIZ]; + RMD160_CTX ctx; + int fd, num, oerrno; + + _DIAGASSERT(filename != NULL); + /* XXX: buf may be NULL ? */ + + RMD160_Init(&ctx); + + if ((fd = open(filename, O_RDONLY)) < 0) + return(0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + RMD160_Update(&ctx, buffer, (size_t)num); + + oerrno = errno; + close(fd); + errno = oerrno; + return(num < 0 ? 0 : RMD160_End(&ctx, buf)); +} + +char * +RMD160_Data(const uint8_t *data, size_t len, char *buf) +{ + RMD160_CTX ctx; + + _DIAGASSERT(data != NULL); + /* XXX: buf may be NULL ? */ + + RMD160_Init(&ctx); + RMD160_Update(&ctx, data, len); + return(RMD160_End(&ctx, buf)); +} diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c new file mode 100644 index 0000000000..3cfe9e3df7 --- /dev/null +++ b/ext/digest/rmd160/rmd160init.c @@ -0,0 +1,34 @@ +/* $RoughId: rmd160init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */ +/* $Id$ */ + +#include "digest.h" +#include "rmd160.h" + +static algo_t rmd160 = { + RMD160_DIGEST_LENGTH, + sizeof(RMD160_CTX), + (hash_init_func_t)RMD160_Init, + (hash_update_func_t)RMD160_Update, + (hash_end_func_t)RMD160_End, + (hash_final_func_t)RMD160_Final, + (hash_equal_func_t)RMD160_Equal, +}; + +void +Init_rmd160() +{ + VALUE mDigest, cDigest_Base, cDigest_RMD160; + ID id_metadata; + + rb_require("digest.so"); + + mDigest = rb_path2class("Digest"); + cDigest_Base = rb_path2class("Digest::Base"); + + cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base); + + id_metadata = rb_intern("metadata"); + + rb_cvar_declare(cDigest_RMD160, id_metadata, + Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160)); +} diff --git a/ext/digest/sha1/.cvsignore b/ext/digest/sha1/.cvsignore new file mode 100644 index 0000000000..fc802ff1c2 --- /dev/null +++ b/ext/digest/sha1/.cvsignore @@ -0,0 +1,2 @@ +Makefile +mkmf.log diff --git a/ext/digest/sha1/MANIFEST b/ext/digest/sha1/MANIFEST new file mode 100644 index 0000000000..f08f240383 --- /dev/null +++ b/ext/digest/sha1/MANIFEST @@ -0,0 +1,5 @@ +extconf.rb +sha1.c +sha1.h +sha1hl.c +sha1init.c diff --git a/ext/digest/sha1/extconf.rb b/ext/digest/sha1/extconf.rb new file mode 100644 index 0000000000..c7d6d4d844 --- /dev/null +++ b/ext/digest/sha1/extconf.rb @@ -0,0 +1,20 @@ +# $RoughId: extconf.rb,v 1.1 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require "mkmf" + +$CFLAGS << " -DHAVE_CONFIG_H -I.." + +$objs = [ + "sha1.#{$OBJEXT}", + "sha1hl.#{$OBJEXT}", + "sha1init.#{$OBJEXT}", +] + +have_header("sys/cdefs.h") + +have_header("inttypes.h") + +have_header("unistd.h") + +create_makefile("digest/sha1") diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c new file mode 100644 index 0000000000..1012ef8751 --- /dev/null +++ b/ext/digest/sha1/sha1.c @@ -0,0 +1,283 @@ +/* $NetBSD: sha1.c,v 1.2 2001/03/22 09:51:48 agc Exp $ */ +/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ +/* $RoughId: sha1.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#include "sha1.h" + +#define SHA1HANDSOFF /* Copies data before messing with it. */ + +#if defined(_KERNEL) || defined(_STANDALONE) +#include +#include +#define _DIAGASSERT(x) (void)0 +#else +/* #include "namespace.h" */ +#include +#include +#endif + +#ifndef _DIAGASSERT +#define _DIAGASSERT(cond) assert(cond) +#endif + +/* + * XXX Kludge until there is resolution regarding mem*() functions + * XXX in the kernel. + */ +#if defined(_KERNEL) || defined(_STANDALONE) +#define memcpy(s, d, l) bcopy((d), (s), (l)) +#endif + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +#ifndef WORDS_BIGENDIAN +# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +# define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +typedef union { + uint8_t c[64]; + uint32_t l[16]; +} CHAR64LONG16; + +#ifdef __sparc_v9__ +void do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); +void do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *); + +#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) +#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) +#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) +#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) +#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) + +void +do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); nR0(c,d,e,a,b, 3); + nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); + nR0(c,d,e,a,b, 8); nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); + nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); nR0(a,b,c,d,e,15); + nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); +} + +void +do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); nR2(c,d,e,a,b,23); + nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); + nR2(c,d,e,a,b,28); nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); + nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); nR2(a,b,c,d,e,35); + nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); +} + +void +do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); nR3(c,d,e,a,b,43); + nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); + nR3(c,d,e,a,b,48); nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); + nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); nR3(a,b,c,d,e,55); + nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); +} + +void +do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LONG16 *block) +{ + nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); nR4(c,d,e,a,b,63); + nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); + nR4(c,d,e,a,b,68); nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); + nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); nR4(a,b,c,d,e,75); + nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); +} +#endif + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void SHA1_Transform(state, buffer) + uint32_t state[5]; + const uint8_t buffer[64]; +{ + uint32_t a, b, c, d, e; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; +#endif + + _DIAGASSERT(buffer != 0); + _DIAGASSERT(state != 0); + +#ifdef SHA1HANDSOFF + block = &workspace; + (void)memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *)(void *)buffer; +#endif + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + +#ifdef __sparc_v9__ + do_R01(&a, &b, &c, &d, &e, block); + do_R2(&a, &b, &c, &d, &e, block); + do_R3(&a, &b, &c, &d, &e, block); + do_R4(&a, &b, &c, &d, &e, block); +#else + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); +#endif + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* + * SHA1_Init - Initialize new context + */ +void SHA1_Init(context) + SHA1_CTX *context; +{ + + _DIAGASSERT(context != 0); + + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* + * Run your data through this. + */ +void SHA1_Update(context, data, len) + SHA1_CTX *context; + const uint8_t *data; + size_t len; +{ + uint32_t i, j; + + _DIAGASSERT(context != 0); + _DIAGASSERT(data != 0); + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1] += (len>>29)+1; + j = (j >> 3) & 63; + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1_Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + SHA1_Transform(context->state, &data[i]); + j = 0; + } else { + i = 0; + } + (void)memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* + * Add padding and return the message digest. + */ +void SHA1_Final(digest, context) + uint8_t digest[20]; + SHA1_CTX* context; +{ + size_t i; + uint8_t finalcount[8]; + + _DIAGASSERT(digest != 0); + _DIAGASSERT(context != 0); + + for (i = 0; i < 8; i++) { + finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1_Update(context, (const uint8_t *)"\200", 1); + while ((context->count[0] & 504) != 448) + SHA1_Update(context, (const uint8_t *)"\0", 1); + SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ + + if (digest) { + for (i = 0; i < 20; i++) + digest[i] = (uint8_t) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } +} + +int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) { + return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0 + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0; +} diff --git a/ext/digest/sha1/sha1.h b/ext/digest/sha1/sha1.h new file mode 100644 index 0000000000..22e06d29b8 --- /dev/null +++ b/ext/digest/sha1/sha1.h @@ -0,0 +1,37 @@ +/* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */ +/* $RoughId: sha1.h,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SYS_SHA1_H_ +#define _SYS_SHA1_H_ + +#include "defs.h" + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + uint8_t buffer[64]; +} SHA1_CTX; + +void SHA1_Transform _((uint32_t state[5], const uint8_t buffer[64])); +void SHA1_Init _((SHA1_CTX *context)); +void SHA1_Update _((SHA1_CTX *context, const uint8_t *data, size_t len)); +void SHA1_Final _((uint8_t digest[20], SHA1_CTX *context)); +int SHA1_Equal _((SHA1_CTX *pctx1, SHA1_CTX *pctx2)); +#ifndef _KERNEL +char *SHA1_End _((SHA1_CTX *, char *)); +char *SHA1_File _((char *, char *)); +char *SHA1_Data _((const uint8_t *, size_t, char *)); +#endif /* _KERNEL */ + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) + +#endif /* _SYS_SHA1_H_ */ diff --git a/ext/digest/sha1/sha1hl.c b/ext/digest/sha1/sha1hl.c new file mode 100644 index 0000000000..d1a236b22c --- /dev/null +++ b/ext/digest/sha1/sha1hl.c @@ -0,0 +1,102 @@ +/* $NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $ */ +/* $RoughId: sha1hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/* sha1hl.c + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +/* #include "namespace.h" */ + +#include "sha1.h" +#include + +#include +#include +#include +#include +#if defined(HAVE_UNISTD_H) +# include +#endif + +#if defined(LIBC_SCCS) && !defined(lint) +/* __RCSID("$NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $"); */ +#endif /* LIBC_SCCS and not lint */ + +#ifndef _DIAGASSERT +#define _DIAGASSERT(cond) assert(cond) +#endif + + +/* ARGSUSED */ +char * +SHA1_End(ctx, buf) + SHA1_CTX *ctx; + char *buf; +{ + int i; + char *p = buf; + uint8_t digest[20]; + static const char hex[]="0123456789abcdef"; + + _DIAGASSERT(ctx != NULL); + /* buf may be NULL */ + + if (p == NULL && (p = malloc(41)) == NULL) + return 0; + + SHA1_Final(digest,ctx); + for (i = 0; i < 20; i++) { + p[i + i] = hex[((uint32_t)digest[i]) >> 4]; + p[i + i + 1] = hex[digest[i] & 0x0f]; + } + p[i + i] = '\0'; + return(p); +} + +char * +SHA1_File (filename, buf) + char *filename; + char *buf; +{ + uint8_t buffer[BUFSIZ]; + SHA1_CTX ctx; + int fd, num, oerrno; + + _DIAGASSERT(filename != NULL); + /* XXX: buf may be NULL ? */ + + SHA1_Init(&ctx); + + if ((fd = open(filename,O_RDONLY)) < 0) + return(0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + SHA1_Update(&ctx, buffer, (size_t)num); + + oerrno = errno; + close(fd); + errno = oerrno; + return(num < 0 ? 0 : SHA1_End(&ctx, buf)); +} + +char * +SHA1_Data (data, len, buf) + const uint8_t *data; + size_t len; + char *buf; +{ + SHA1_CTX ctx; + + _DIAGASSERT(data != NULL); + /* XXX: buf may be NULL ? */ + + SHA1_Init(&ctx); + SHA1_Update(&ctx, data, len); + return(SHA1_End(&ctx, buf)); +} diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c new file mode 100644 index 0000000000..ecf4aeb198 --- /dev/null +++ b/ext/digest/sha1/sha1init.c @@ -0,0 +1,34 @@ +/* $RoughId: sha1init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +#include "digest.h" +#include "sha1.h" + +static algo_t sha1 = { + SHA1_DIGEST_LENGTH, + sizeof(SHA1_CTX), + (hash_init_func_t)SHA1_Init, + (hash_update_func_t)SHA1_Update, + (hash_end_func_t)SHA1_End, + (hash_final_func_t)SHA1_Final, + (hash_equal_func_t)SHA1_Equal, +}; + +void +Init_sha1() +{ + VALUE mDigest, cDigest_Base, cDigest_SHA1; + ID id_metadata; + + rb_require("digest.so"); + + mDigest = rb_path2class("Digest"); + cDigest_Base = rb_path2class("Digest::Base"); + + cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base); + + id_metadata = rb_intern("metadata"); + + rb_cvar_declare(cDigest_SHA1, id_metadata, + Data_Wrap_Struct(rb_cObject, 0, 0, &sha1)); +} diff --git a/ext/digest/sha2/.cvsignore b/ext/digest/sha2/.cvsignore new file mode 100644 index 0000000000..fc802ff1c2 --- /dev/null +++ b/ext/digest/sha2/.cvsignore @@ -0,0 +1,2 @@ +Makefile +mkmf.log diff --git a/ext/digest/sha2/MANIFEST b/ext/digest/sha2/MANIFEST new file mode 100644 index 0000000000..03fbb0fcda --- /dev/null +++ b/ext/digest/sha2/MANIFEST @@ -0,0 +1,5 @@ +extconf.rb +sha2.c +sha2.h +sha2hl.c +sha2init.c diff --git a/ext/digest/sha2/extconf.rb b/ext/digest/sha2/extconf.rb new file mode 100644 index 0000000000..e7ca707cf4 --- /dev/null +++ b/ext/digest/sha2/extconf.rb @@ -0,0 +1,20 @@ +# $RoughId: extconf.rb,v 1.1 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require "mkmf" + +$CFLAGS << " -DHAVE_CONFIG_H -I.." + +$objs = [ + "sha2.#{$OBJEXT}", + "sha2hl.#{$OBJEXT}", + "sha2init.#{$OBJEXT}", +] + +have_header("sys/cdefs.h") + +have_header("inttypes.h") + +have_header("unistd.h") + +create_makefile("digest/sha2") diff --git a/ext/digest/sha2/sha2.c b/ext/digest/sha2/sha2.c new file mode 100644 index 0000000000..a04534a831 --- /dev/null +++ b/ext/digest/sha2/sha2.c @@ -0,0 +1,937 @@ +/* + * sha2.c + * + * Version 1.0.0beta1 + * + * Written by Aaron D. Gifford + * + * Copyright 2000 Aaron D. Gifford. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* $RoughId: sha2.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +#include +#include /* memcpy()/memset() or bcopy()/bzero() */ +#include /* assert() */ +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +typedef uint8_t sha2_byte; /* Exactly 1 byte */ +typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +typedef uint64_t sha2_word64; /* Exactly 8 bytes */ + +#if defined(__GNUC__) +#define ULL(number) number##ULL +#else +#define ULL(number) (uint64_t)(number) +#endif + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#ifndef WORDS_BIGENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & ULL(0xff00ff00ff00ff00)) >> 8) | \ + ((tmp & ULL(0x00ff00ff00ff00ff)) << 8); \ + (x) = ((tmp & ULL(0xffff0000ffff0000)) >> 16) | \ + ((tmp & ULL(0x0000ffff0000ffff)) << 16); \ +} +#endif + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void SHA512_Last(SHA512_CTX*); +void SHA256_Transform(SHA256_CTX*, const sha2_word32*); +void SHA512_Transform(SHA512_CTX*, const sha2_word64*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +const static sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const static sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +const static sha2_word64 K512[80] = { + ULL(0x428a2f98d728ae22), ULL(0x7137449123ef65cd), + ULL(0xb5c0fbcfec4d3b2f), ULL(0xe9b5dba58189dbbc), + ULL(0x3956c25bf348b538), ULL(0x59f111f1b605d019), + ULL(0x923f82a4af194f9b), ULL(0xab1c5ed5da6d8118), + ULL(0xd807aa98a3030242), ULL(0x12835b0145706fbe), + ULL(0x243185be4ee4b28c), ULL(0x550c7dc3d5ffb4e2), + ULL(0x72be5d74f27b896f), ULL(0x80deb1fe3b1696b1), + ULL(0x9bdc06a725c71235), ULL(0xc19bf174cf692694), + ULL(0xe49b69c19ef14ad2), ULL(0xefbe4786384f25e3), + ULL(0x0fc19dc68b8cd5b5), ULL(0x240ca1cc77ac9c65), + ULL(0x2de92c6f592b0275), ULL(0x4a7484aa6ea6e483), + ULL(0x5cb0a9dcbd41fbd4), ULL(0x76f988da831153b5), + ULL(0x983e5152ee66dfab), ULL(0xa831c66d2db43210), + ULL(0xb00327c898fb213f), ULL(0xbf597fc7beef0ee4), + ULL(0xc6e00bf33da88fc2), ULL(0xd5a79147930aa725), + ULL(0x06ca6351e003826f), ULL(0x142929670a0e6e70), + ULL(0x27b70a8546d22ffc), ULL(0x2e1b21385c26c926), + ULL(0x4d2c6dfc5ac42aed), ULL(0x53380d139d95b3df), + ULL(0x650a73548baf63de), ULL(0x766a0abb3c77b2a8), + ULL(0x81c2c92e47edaee6), ULL(0x92722c851482353b), + ULL(0xa2bfe8a14cf10364), ULL(0xa81a664bbc423001), + ULL(0xc24b8b70d0f89791), ULL(0xc76c51a30654be30), + ULL(0xd192e819d6ef5218), ULL(0xd69906245565a910), + ULL(0xf40e35855771202a), ULL(0x106aa07032bbd1b8), + ULL(0x19a4c116b8d2d0c8), ULL(0x1e376c085141ab53), + ULL(0x2748774cdf8eeb99), ULL(0x34b0bcb5e19b48a8), + ULL(0x391c0cb3c5c95a63), ULL(0x4ed8aa4ae3418acb), + ULL(0x5b9cca4f7763e373), ULL(0x682e6ff3d6b2b8a3), + ULL(0x748f82ee5defb2fc), ULL(0x78a5636f43172f60), + ULL(0x84c87814a1f0ab72), ULL(0x8cc702081a6439ec), + ULL(0x90befffa23631e28), ULL(0xa4506cebde82bde9), + ULL(0xbef9a3f7b2c67915), ULL(0xc67178f2e372532b), + ULL(0xca273eceea26619c), ULL(0xd186b8c721c0c207), + ULL(0xeada7dd6cde0eb1e), ULL(0xf57d4f7fee6ed178), + ULL(0x06f067aa72176fba), ULL(0x0a637dc5a2c898a6), + ULL(0x113f9804bef90dae), ULL(0x1b710b35131c471b), + ULL(0x28db77f523047d84), ULL(0x32caab7b40c72493), + ULL(0x3c9ebe0a15c9bebc), ULL(0x431d67c49c100d4c), + ULL(0x4cc5d4becb3e42b6), ULL(0x597f299cfc657e2a), + ULL(0x5fcb6fab3ad6faec), ULL(0x6c44198c4a475817) +}; + +/* Initial hash value H for SHA-384 */ +const static sha2_word64 sha384_initial_hash_value[8] = { + ULL(0xcbbb9d5dc1059ed8), + ULL(0x629a292a367cd507), + ULL(0x9159015a3070dd17), + ULL(0x152fecd8f70e5939), + ULL(0x67332667ffc00b31), + ULL(0x8eb44a8768581511), + ULL(0xdb0c2e0d64f98fa7), + ULL(0x47b5481dbefa4fa4) +}; + +/* Initial hash value H for SHA-512 */ +const static sha2_word64 sha512_initial_hash_value[8] = { + ULL(0x6a09e667f3bcc908), + ULL(0xbb67ae8584caa73b), + ULL(0x3c6ef372fe94f82b), + ULL(0xa54ff53a5f1d36f1), + ULL(0x510e527fade682d1), + ULL(0x9b05688c2b3e6c1f), + ULL(0x1f83d9abfb41bd6b), + ULL(0x5be0cd19137e2179) +}; + + +/*** SHA-256: *********************************************************/ +void SHA256_Init(SHA256_CTX* context) { + if (context == (SHA256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#ifndef WORDS_BIGENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#ifndef WORDS_BIGENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != NULL && data != NULL); + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (const sha2_word32*)data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != NULL); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; +#ifndef WORDS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace < SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(SHA256_CTX)); + usedspace = 0; +} + +int SHA256_Equal(SHA256_CTX* pctx1, SHA256_CTX* pctx2) { + return pctx1->bitcount == pctx2->bitcount + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0; +} + +/*** SHA-512: *********************************************************/ +void SHA512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#ifndef WORDS_BIGENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#ifndef WORDS_BIGENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != NULL && data != NULL); + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (const sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (const sha2_word64*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; +#ifndef WORDS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace < SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (const sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (const sha2_word64*)context->buffer); +} + +void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != NULL); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last(context); + + /* Save the hash data for output: */ +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA512_CTX)); +} + +int SHA512_Equal(SHA512_CTX* pctx1, SHA512_CTX* pctx2) { + return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0 + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0; +} + +/*** SHA-384: *********************************************************/ +void SHA384_Init(SHA384_CTX* context) { + if (context == (SHA384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { + SHA512_Update((SHA512_CTX*)context, data, len); +} + +void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != NULL); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last((SHA512_CTX*)context); + + /* Save the hash data for output: */ +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA384_CTX)); +} + +int SHA384_Equal(SHA384_CTX* pctx1, SHA384_CTX* pctx2) { + return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0 + && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0 + && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0; +} diff --git a/ext/digest/sha2/sha2.h b/ext/digest/sha2/sha2.h new file mode 100644 index 0000000000..f5c7fd42aa --- /dev/null +++ b/ext/digest/sha2/sha2.h @@ -0,0 +1,107 @@ +/* + * sha2.h + * + * Version 1.0.0beta1 + * + * Written by Aaron D. Gifford + * + * Copyright 2000 Aaron D. Gifford. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* $RoughId: sha2.h,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "defs.h" + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ + +typedef struct _SHA256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + uint64_t state[8]; + uint64_t bitcount[2]; + uint8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +typedef SHA512_CTX SHA384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +void SHA256_Init _((SHA256_CTX *)); +void SHA256_Update _((SHA256_CTX*, const uint8_t*, size_t)); +void SHA256_Final _((uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*)); +char* SHA256_End _((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH])); +char* SHA256_Data _((const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH])); +char *SHA256_File _((char *, char *)); +int SHA256_Equal _((SHA256_CTX*, SHA256_CTX*)); + +void SHA384_Init _((SHA384_CTX*)); +void SHA384_Update _((SHA384_CTX*, const uint8_t*, size_t)); +void SHA384_Final _((uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*)); +char* SHA384_End _((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH])); +char* SHA384_Data _((const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH])); +char *SHA384_File _((char *, char *)); +int SHA384_Equal _((SHA384_CTX*, SHA384_CTX*)); + +void SHA512_Init _((SHA512_CTX*)); +void SHA512_Update _((SHA512_CTX*, const uint8_t*, size_t)); +void SHA512_Final _((uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*)); +char* SHA512_End _((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH])); +char* SHA512_Data _((const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH])); +char *SHA512_File _((char *, char *)); +int SHA512_Equal _((SHA512_CTX*, SHA512_CTX*)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SHA2_H__ */ + diff --git a/ext/digest/sha2/sha2hl.c b/ext/digest/sha2/sha2hl.c new file mode 100644 index 0000000000..03fde538c3 --- /dev/null +++ b/ext/digest/sha2/sha2hl.c @@ -0,0 +1,252 @@ +/* $NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $ */ +/* $RoughId: sha2hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */ +/* $Id$ */ + +/* + * sha2hl.c + * This code includes some functions taken from sha2.c, hence the + * following licence reproduction. + * + * This code is not a verbatim copy, since some routines have been added, + * and some bugs have been fixed. + * + * Version 1.0.0beta1 + * + * Written by Aaron D. Gifford + * + * Copyright 2000 Aaron D. Gifford. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sha2.h" + +#ifndef lint +/* __RCSID("$NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $"); */ +#endif /* not lint */ + +/* #include "namespace.h" */ + +#include +#include +#include +#include +#include +#include +#if defined(HAVE_UNISTD_H) +# include +#endif + +#ifndef _DIAGASSERT +#define _DIAGASSERT(cond) assert(cond) +#endif + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char sha2_hex_digits[] = "0123456789abcdef"; + +char * +SHA256_File(char *filename, char *buf) +{ + uint8_t buffer[BUFSIZ * 20]; + SHA256_CTX ctx; + int fd, num, oerrno; + + _DIAGASSERT(filename != NULL); + /* XXX: buf may be NULL ? */ + + SHA256_Init(&ctx); + + if ((fd = open(filename, O_RDONLY)) < 0) + return (0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + SHA256_Update(&ctx, buffer, (size_t) num); + + oerrno = errno; + close(fd); + errno = oerrno; + return (num < 0 ? 0 : SHA256_End(&ctx, buf)); +} + + +char * +SHA256_End(SHA256_CTX *ctx, char buffer[]) +{ + uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest; + uint8_t *ret; + int i; + + /* Sanity check: */ + assert(ctx != NULL); + + if ((ret = buffer) != NULL) { + SHA256_Final(digest, ctx); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char) 0; + } else { + (void) memset(ctx, 0, sizeof(SHA256_CTX)); + } + (void) memset(digest, 0, SHA256_DIGEST_LENGTH); + return ret; +} + +char * +SHA256_Data(const uint8_t * data, size_t len, char *digest) +{ + SHA256_CTX ctx; + + SHA256_Init(&ctx); + SHA256_Update(&ctx, data, len); + return SHA256_End(&ctx, digest); +} + +char * +SHA384_File(char *filename, char *buf) +{ + SHA384_CTX ctx; + uint8_t buffer[BUFSIZ * 20]; + int fd, num, oerrno; + + _DIAGASSERT(filename != NULL); + /* XXX: buf may be NULL ? */ + + SHA384_Init(&ctx); + + if ((fd = open(filename, O_RDONLY)) < 0) + return (0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + SHA384_Update(&ctx, buffer, (size_t) num); + + oerrno = errno; + close(fd); + errno = oerrno; + return (num < 0 ? 0 : SHA384_End(&ctx, buf)); +} + +char * +SHA384_End(SHA384_CTX * ctx, char buffer[]) +{ + uint8_t digest[SHA384_DIGEST_LENGTH], *d = digest; + uint8_t *ret; + int i; + + /* Sanity check: */ + assert(ctx != NULL); + + if ((ret = buffer) != NULL) { + SHA384_Final(digest, ctx); + + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char) 0; + } else { + (void) memset(ctx, 0, sizeof(SHA384_CTX)); + } + (void) memset(digest, 0, SHA384_DIGEST_LENGTH); + return ret; +} + +char * +SHA384_Data(const uint8_t * data, size_t len, char *digest) +{ + SHA384_CTX ctx; + + SHA384_Init(&ctx); + SHA384_Update(&ctx, data, len); + return SHA384_End(&ctx, digest); +} + +char * +SHA512_File(char *filename, char *buf) +{ + SHA512_CTX ctx; + uint8_t buffer[BUFSIZ * 20]; + int fd, num, oerrno; + + _DIAGASSERT(filename != NULL); + /* XXX: buf may be NULL ? */ + + SHA512_Init(&ctx); + + if ((fd = open(filename, O_RDONLY)) < 0) + return (0); + + while ((num = read(fd, buffer, sizeof(buffer))) > 0) + SHA512_Update(&ctx, buffer, (size_t) num); + + oerrno = errno; + close(fd); + errno = oerrno; + return (num < 0 ? 0 : SHA512_End(&ctx, buf)); +} + +char * +SHA512_End(SHA512_CTX * ctx, char buffer[]) +{ + uint8_t digest[SHA512_DIGEST_LENGTH], *d = digest; + uint8_t *ret; + int i; + + /* Sanity check: */ + assert(ctx != NULL); + + if ((ret = buffer) != NULL) { + SHA512_Final(digest, ctx); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char) 0; + } else { + (void) memset(ctx, 0, sizeof(SHA512_CTX)); + } + (void) memset(digest, 0, SHA512_DIGEST_LENGTH); + return ret; +} + +char * +SHA512_Data(const uint8_t * data, size_t len, char *digest) +{ + SHA512_CTX ctx; + + SHA512_Init(&ctx); + SHA512_Update(&ctx, data, len); + return SHA512_End(&ctx, digest); +} diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c new file mode 100644 index 0000000000..d7666aadf9 --- /dev/null +++ b/ext/digest/sha2/sha2init.c @@ -0,0 +1,47 @@ +/* $RoughId: sha2init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */ +/* $Id$ */ + +#include "digest.h" +#include "sha2.h" + +#define FOREACH_BITLEN(func) func(256) func(384) func(512) + +#define DEFINE_ALGO_METADATA(bitlen) \ +static algo_t sha##bitlen = { \ + SHA##bitlen##_DIGEST_LENGTH, \ + sizeof(SHA##bitlen##_CTX), \ + (hash_init_func_t)SHA##bitlen##_Init, \ + (hash_update_func_t)SHA##bitlen##_Update, \ + (hash_end_func_t)SHA##bitlen##_End, \ + (hash_final_func_t)SHA##bitlen##_Final, \ + (hash_equal_func_t)SHA##bitlen##_Equal, \ +}; + +FOREACH_BITLEN(DEFINE_ALGO_METADATA) + +void +Init_sha2() +{ + VALUE mDigest, cDigest_Base; + ID id_metadata; + +#define DECLARE_ALGO_CLASS(bitlen) \ + VALUE cDigest_SHA##bitlen; + + FOREACH_BITLEN(DECLARE_ALGO_CLASS) + + rb_require("digest.so"); + + id_metadata = rb_intern("metadata"); + + mDigest = rb_path2class("Digest"); + cDigest_Base = rb_path2class("Digest::Base"); + +#define DEFINE_ALGO_CLASS(bitlen) \ + cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \ +\ + rb_cvar_declare(cDigest_SHA##bitlen, id_metadata, \ + Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen)); + + FOREACH_BITLEN(DEFINE_ALGO_CLASS) +} diff --git a/ext/digest/test.rb b/ext/digest/test.rb new file mode 100644 index 0000000000..2f29948bb6 --- /dev/null +++ b/ext/digest/test.rb @@ -0,0 +1,100 @@ +#!/usr/bin/env ruby +# +# $RoughId: test.rb,v 1.4 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +require 'runit/testcase' +require 'runit/cui/testrunner' + +require 'digest/md5' +require 'digest/rmd160' +require 'digest/sha1' +require 'digest/sha2' +include Digest + +class TestDigest < RUNIT::TestCase + ALGOS = [ + MD5, + SHA1, + SHA256, + SHA384, + SHA512, + RMD160 + ] + + DATA = { + "abc" => { + MD5 => "900150983cd24fb0d6963f7d28e17f72", + SHA1 => "a9993e364706816aba3e25717850c26c9cd0d89d", + SHA256 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + SHA384 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", + SHA512 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + RMD160 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" + }, + + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" => { + MD5 => "8215ef0796a20bcaaae116d3876c664a", + SHA1 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1", + SHA256 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + SHA384 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b", + SHA512 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", + RMD160 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b" + } + } + + def test_s_hexdigest + ALGOS.each do |algo| + DATA.each do |str, table| + assert_equal(table[algo], algo.hexdigest(str)) + end + end + end + + def test_s_digest + ALGOS.each do |algo| + DATA.each do |str, table| + assert_equal([table[algo]].pack("H*"), algo.digest(str)) + end + end + end + + def test_update + # This test is also for digest() and hexdigest() + + str = "ABC" + + ALGOS.each do |algo| + md = algo.new + md.update str + assert_equal(algo.hexdigest(str), md.hexdigest) + assert_equal(algo.digest(str), md.digest) + end + end + + def test_eq + # This test is also for clone() + + ALGOS.each do |algo| + md1 = algo.new("ABC") + + assert_equal(md1, md1.clone) + + md2 = algo.new + md2 << "A" + + assert(md1 != md2) + + md2 << "BC" + + assert_equal(md1, md2) + end + end +end + +if $0 == __FILE__ + suite = RUNIT::TestSuite.new + + suite.add_test(TestDigest.suite) + + RUNIT::CUI::TestRunner.run(suite) +end diff --git a/ext/digest/test.sh b/ext/digest/test.sh new file mode 100644 index 0000000000..88b34b04c5 --- /dev/null +++ b/ext/digest/test.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# $RoughId: test.sh,v 1.5 2001/07/13 15:38:27 knu Exp $ +# $Id$ + +RUBY=${RUBY:=ruby} +MAKE=${MAKE:=make} +CFLAGS=${CFLAGS:=-Wall} + +${RUBY} extconf.rb --with-cflags="${CFLAGS}" +${MAKE} clean +${MAKE} + +mkdir -p lib/digest + +for algo in md5 rmd160 sha1 sha2; do + (cd $algo && + ${RUBY} extconf.rb --with-cflags="${CFLAGS}"; + ${MAKE} clean; + ${MAKE}) + ln -sf ../../$algo/$algo.so lib/digest/ +done + +${RUBY} -I. -I./lib test.rb + +rm lib/digest/*.so +rmdir lib/digest diff --git a/ext/md5/.cvsignore b/ext/md5/.cvsignore deleted file mode 100644 index f3c7a7c5da..0000000000 --- a/ext/md5/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST deleted file mode 100644 index 189a482afb..0000000000 --- a/ext/md5/MANIFEST +++ /dev/null @@ -1,8 +0,0 @@ -MANIFEST -depend -extconf.rb -md5.txt -md5.txt.jp -md5.h -md5c.c -md5init.c diff --git a/ext/md5/depend b/ext/md5/depend deleted file mode 100644 index 14427861f8..0000000000 --- a/ext/md5/depend +++ /dev/null @@ -1,2 +0,0 @@ -md5c.o: md5c.c md5.h $(topdir)/config.h -md5init.o: md5init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h md5.h diff --git a/ext/md5/extconf.rb b/ext/md5/extconf.rb deleted file mode 100644 index a57a976a39..0000000000 --- a/ext/md5/extconf.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'mkmf' -$CFLAGS += " -DHAVE_CONFIG_H" -create_makefile('md5') diff --git a/ext/md5/md5.h b/ext/md5/md5.h deleted file mode 100644 index a2d7b34156..0000000000 --- a/ext/md5/md5.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/*$Id$ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.h is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . - 1999-05-03 lpd Original version. - */ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This code has some adaptations for the Ghostscript environment, but it - * will compile and run correctly in any environment with 8-bit chars and - * 32-bit ints. Specifically, it assumes that if the following are - * defined, they have the same meaning as in Ghostscript: P1, P2, P3, - * ARCH_IS_BIG_ENDIAN. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -#ifdef P1 -void md5_init(P1(md5_state_t *pms)); -#else -void md5_init(md5_state_t *pms); -#endif - -/* Append a string to the message. */ -#ifdef P3 -void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); -#else -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); -#endif - -/* Finish the message and return the digest. */ -#ifdef P2 -void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); -#else -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); -#endif - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* md5_INCLUDED */ diff --git a/ext/md5/md5.txt b/ext/md5/md5.txt deleted file mode 100644 index a3c50ff407..0000000000 --- a/ext/md5/md5.txt +++ /dev/null @@ -1,51 +0,0 @@ -.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996 - -** MD5(Class) - -A class to implement MD5 Message-Digest Algorithm by RSA Data -Security, Inc., described in RFC1321. - -Superclass: Object - -Class Methods: - - new([str]) - md5([str]) - - Creates a new MD5 object. If a string argument is given, it - is added to the object. (see update.) - -Methods: - - clone - - Copies the MD5 object. - - digest - - Returns the MD5 hash of the added strings as a string of 16 - bytes. - - hexdigest - - Returns the MD5 hash of the added strings as a string of 32 - hexadecimal digits. This method is equal to: - - def hexdigest - ret = '' - digest.each_byte {|i| ret << sprintf('%02x', i) } - ret - end - - update(str) - << str - - Update the MD5 object with the string str. Repeated calls are - equivalent to a single call with the concatenation of all the - arguments, i.e. m.update(a); m.update(b) is equivalent to - m.update(a+b) and m << a << b is equivalent to m << a+b. - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/md5/md5.txt.jp b/ext/md5/md5.txt.jp deleted file mode 100644 index fdb4bcc04f..0000000000 --- a/ext/md5/md5.txt.jp +++ /dev/null @@ -1,52 +0,0 @@ -.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996 - -** MD5(クラス) - -RFC1321に記述されているRSA Data Security, Inc. の MD5 Message-Digest -Algorithmを実装するクラス。 - -Superclass: Object - -Class Methods: - - new([str]) - md5([str]) - - 新しいMD5オブジェクトを生成する.文字列引数が与えられるとそれ - を追加する(see update)。 - -Methods: - - clone - - MD5オブジェクトの複製を作る。 - - digest - - 今までに追加した文字列に対するハッシュ値を16バイト長の文字列で - 返す。 - - hexdigest - - 今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って - 16進数の列を示す'fe5c2235f48d2bcc911afabea23cd5aa'のような32文字 - の文字列にエンコードして返す。Rubyで書くと以下と同じ。 - - def hexdigest - ret = '' - digest.each_byte {|i| ret << sprintf('%02x', i) } - ret - end - - update(str) - << str - - MD5オブジェクトに文字列を追加する。複数回updateを呼ぶことは文 - 字列を連結してupdateを呼ぶことと等しい。すなわち m.update(a); - m.update(b) は m.update(a+b) と、 m << a << b は m << a+b と - それぞれ等価である。 - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/md5/md5c.c b/ext/md5/md5c.c deleted file mode 100644 index 854f79eba0..0000000000 --- a/ext/md5/md5c.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/*$Id$ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; - made test program self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -#include "md5.h" - -#ifdef TEST -/* - * Compile with -DTEST to create a self-contained executable test program. - * The test program should print out the same values as given in section - * A.5 of RFC 1321, reproduced below. - */ -#include -main() -{ - static const char *const test[7*2] = { - "", "d41d8cd98f00b204e9800998ecf8427e", - "a", "0cc175b9c0f1b6a831c399e269772661", - "abc", "900150983cd24fb0d6963f7d28e17f72", - "message digest", "f96b697d7cb7938d525a2f31aaf161d0", - "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "d174ab98d277d9f5a5611c2c9f419d9f", - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" - }; - int i; - - for (i = 0; i < 7*2; i += 2) { - md5_state_t state; - md5_byte_t digest[16]; - char hex_output[16*2 + 1]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); - md5_finish(&state, digest); - printf("MD5 (\"%s\") = ", test[i]); - for (di = 0; di < 16; ++di) - sprintf(hex_output + di * 2, "%02x", digest[di]); - puts(hex_output); - if (strcmp(hex_output, test[i + 1])) - printf("**** ERROR, should be: %s\n", test[i + 1]); - } - return 0; -} -#endif /* TEST */ - - -/* - * For reference, here is the program that computed the T values. - */ -#ifdef COMPUTE_T_VALUES -#include -main() -{ - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - - /* - * The following nonsense is only to avoid compiler warnings about - * "integer constant is unsigned in ANSI C, signed with -traditional". - */ - if (v >> 31) { - printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i, - v, (unsigned long)(unsigned int)(~v)); - } else { - printf("#define T%d 0x%08lx\n", i, v); - } - } - return 0; -} -#endif /* COMPUTE_T_VALUES */ -/* - * End of T computation program. - */ -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - -#ifndef ARCH_IS_BIG_ENDIAN -# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ -#endif -#if ARCH_IS_BIG_ENDIAN - - /* - * On big-endian machines, we must arrange the bytes in the right - * order. (This also works on machines of unknown byte order.) - */ - md5_word_t X[16]; - const md5_byte_t *xp = data; - int i; - - for (i = 0; i < 16; ++i, xp += 4) - X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - -#else /* !ARCH_IS_BIG_ENDIAN */ - - /* - * On little-endian machines, we can process properly aligned data - * without copying it. - */ - md5_word_t xbuf[16]; - const md5_word_t *X; - - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } -#endif - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c deleted file mode 100644 index f491b65a27..0000000000 --- a/ext/md5/md5init.c +++ /dev/null @@ -1,123 +0,0 @@ -/************************************************ - - md5init.c - - - $Author$ - created at: Fri Aug 2 09:24:12 JST 1996 - - Copyright (C) 1995-2001 Yukihiro Matsumoto - -************************************************/ -/* This module provides an interface to the RSA Data Security, - Inc. MD5 Message-Digest Algorithm, described in RFC 1321. */ - -#include "ruby.h" -#include "md5.h" - -static VALUE cMD5; - -static VALUE -md5i_update(obj, str) - VALUE obj, str; -{ - md5_state_t *md5; - - StringValue(str); - Data_Get_Struct(obj, md5_state_t, md5); - md5_append(md5, RSTRING(str)->ptr, RSTRING(str)->len); - - return obj; -} - -static VALUE -md5i_digest(obj) - VALUE obj; -{ - md5_state_t *md5, ctx; - md5_byte_t digest[16]; - - Data_Get_Struct(obj, md5_state_t, md5); - ctx = *md5; - md5_finish(&ctx, digest); - - return rb_str_new(digest, 16); -} - -static VALUE -md5i_hexdigest(obj) - VALUE obj; -{ - md5_state_t *md5, ctx; - md5_byte_t digest[16]; - char buf[33]; - int i; - - Data_Get_Struct(obj, md5_state_t, md5); - ctx = *md5; - md5_finish(&ctx, digest); - - for (i=0; i<16; i++) { - sprintf(buf+i*2, "%02x", digest[i]); - } - return rb_str_new(buf, 32); -} - -static VALUE -md5i_clone(obj) - VALUE obj; -{ - md5_state_t *md5, *md5_new; - - Data_Get_Struct(obj, md5_state_t, md5); - obj = Data_Make_Struct(CLASS_OF(obj), md5_state_t, 0, free, md5_new); - *md5_new = *md5; - - return obj; -} - -static VALUE -md5i_init(argc, argv, self) - int argc; - VALUE* argv; - VALUE self; -{ - VALUE str; - - rb_scan_args(argc, argv, "01", &str); - - if (!NIL_P(str)) md5i_update(self, str); - - return self; -} - -static VALUE -md5i_new(argc, argv, class) - int argc; - VALUE* argv; - VALUE class; -{ - VALUE obj; - md5_state_t *md5; - - obj = Data_Make_Struct(class, md5_state_t, 0, free, md5); - md5_init(md5); - rb_obj_call_init(obj, argc, argv); - - return obj; -} - -void -Init_md5() -{ - cMD5 = rb_define_class("MD5", rb_cObject); - - rb_define_singleton_method(cMD5, "new", md5i_new, -1); - rb_define_singleton_method(cMD5, "md5", md5i_new, -1); - - rb_define_method(cMD5, "initialize", md5i_init, -1); - rb_define_method(cMD5, "update", md5i_update, 1); - rb_define_method(cMD5, "<<", md5i_update, 1); - rb_define_method(cMD5, "digest", md5i_digest, 0); - rb_define_method(cMD5, "hexdigest", md5i_hexdigest, 0); - rb_define_method(cMD5, "clone", md5i_clone, 0); -} diff --git a/ext/sha1/.cvsignore b/ext/sha1/.cvsignore deleted file mode 100644 index f3c7a7c5da..0000000000 --- a/ext/sha1/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/ext/sha1/MANIFEST b/ext/sha1/MANIFEST deleted file mode 100644 index d946af1cd8..0000000000 --- a/ext/sha1/MANIFEST +++ /dev/null @@ -1,7 +0,0 @@ -MANIFEST -extconf.rb -sha1-ruby.c -sha1.c -sha1.h -sha1.txt -sha1.txt.jp diff --git a/ext/sha1/extconf.rb b/ext/sha1/extconf.rb deleted file mode 100644 index 32e46cf3d7..0000000000 --- a/ext/sha1/extconf.rb +++ /dev/null @@ -1,3 +0,0 @@ -require 'mkmf' - -create_makefile('sha1') diff --git a/ext/sha1/sha1-ruby.c b/ext/sha1/sha1-ruby.c deleted file mode 100644 index abd704c638..0000000000 --- a/ext/sha1/sha1-ruby.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "ruby.h" -#include "sha1.h" - -static VALUE cSHA1; - -static VALUE -sha1_update(obj, str) - VALUE obj; - struct RString *str; -{ - SHA1_CTX *sha1; - - Check_Type(str, T_STRING); - Data_Get_Struct(obj, SHA1_CTX, sha1); - SHA1Update(sha1, str->ptr, str->len); - - return obj; -} - -static VALUE -sha1_digest(obj) - VALUE obj; -{ - SHA1_CTX *sha1, ctx; - unsigned char digest[20]; - - Data_Get_Struct(obj, SHA1_CTX, sha1); - ctx = *sha1; - SHA1Final(digest, &ctx); - - return rb_str_new(digest, 20); -} - -static VALUE -sha1_hexdigest(obj) - VALUE obj; -{ - SHA1_CTX *sha1, ctx; - unsigned char digest[20]; - char buf[41]; - int i; - - Data_Get_Struct(obj, SHA1_CTX, sha1); - ctx = *sha1; - SHA1Final(digest, &ctx); - - for (i=0; i<20; i++) { - sprintf(buf+i*2, "%02x", digest[i]); - } - return rb_str_new(buf, 40); -} - -static VALUE -sha1_clone(obj) - VALUE obj; -{ - SHA1_CTX *sha1, *sha1_new; - - Data_Get_Struct(obj, SHA1_CTX, sha1); - obj = Data_Make_Struct(CLASS_OF(obj), SHA1_CTX, 0, free, sha1_new); - *sha1_new = *sha1; - - return obj; -} - -static VALUE -sha1_init(argc, argv, self) - int argc; - VALUE* argv; - VALUE self; -{ - VALUE arg; - - rb_scan_args(argc, argv, "01", &arg); - - if (!NIL_P(arg)) sha1_update(self, arg); - - return self; -} - -static VALUE -sha1_new(argc, argv, class) - int argc; - VALUE* argv; - VALUE class; -{ - VALUE obj; - SHA1_CTX *sha1; - - obj = Data_Make_Struct(class, SHA1_CTX, 0, free, sha1); - SHA1Init(sha1); - rb_obj_call_init(obj, argc, argv); - - return obj; -} - -void -Init_sha1() -{ - cSHA1 = rb_define_class("SHA1", rb_cObject); - - rb_define_singleton_method(cSHA1, "new", sha1_new, -1); - rb_define_singleton_method(cSHA1, "sha1", sha1_new, -1); - - rb_define_method(cSHA1, "update", sha1_update, 1); - rb_define_method(cSHA1, "initialize", sha1_init, -1); - rb_define_method(cSHA1, "<<", sha1_update, 1); - rb_define_method(cSHA1, "digest", sha1_digest, 0); - rb_define_method(cSHA1, "hexdigest", sha1_hexdigest, 0); - rb_define_method(cSHA1, "clone", sha1_clone, 0); -} diff --git a/ext/sha1/sha1.c b/ext/sha1/sha1.c deleted file mode 100644 index f6f9fa88f2..0000000000 --- a/ext/sha1/sha1.c +++ /dev/null @@ -1,172 +0,0 @@ -/* -SHA-1 in C -By Steve Reid -100% Public Domain - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#include "sha1.h" - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifdef WORDS_BIGENDIAN -#define blk0(i) block->l[i] -#else /* LITTLE ENDIAN */ -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void -SHA1Transform(state, buffer) - unsigned long state[5]; - unsigned char buffer[64]; -{ -unsigned long a, b, c, d, e; -typedef union { - unsigned char c[64]; - unsigned long l[16]; -} CHAR64LONG16; -CHAR64LONG16* block; -#ifdef SHA1HANDSOFF -static unsigned char workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16*)buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1Init - Initialize new context */ - -void -SHA1Init(context) - SHA1_CTX* context; -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void -SHA1Update(context, data, len) - SHA1_CTX* context; - unsigned char* data; - unsigned int len; -{ -unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void -SHA1Final(digest, context) - unsigned char digest[20]; - SHA1_CTX* context; -{ -unsigned long i, j; -unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (unsigned char *)"\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1Update(context, (unsigned char *)"\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ - SHA1Transform(context->state, context->buffer); -#endif -} diff --git a/ext/sha1/sha1.h b/ext/sha1/sha1.h deleted file mode 100644 index f988476a1b..0000000000 --- a/ext/sha1/sha1.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _SHA1_H -#define _SHA1_H - -#include "config.h" - -#ifdef HAVE_PROTOTYPES -#define PROTOTYPES 1 -#endif -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif - -#if PROTOTYPES -#define __P(x) x -#else -#define __P(x) () -#endif - -#include -#include - -typedef struct { - unsigned long state[5]; - unsigned long count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -void SHA1Transform __P((unsigned long state[5], unsigned char buffer[64])); -void SHA1Init __P((SHA1_CTX* context)); -void SHA1Update __P((SHA1_CTX* context, unsigned char* data, unsigned int len)); -void SHA1Final __P((unsigned char digest[20], SHA1_CTX* context)); - -#endif /* _SHA1_H */ diff --git a/ext/sha1/sha1.txt b/ext/sha1/sha1.txt deleted file mode 100644 index 0ddc0a6ae8..0000000000 --- a/ext/sha1/sha1.txt +++ /dev/null @@ -1,56 +0,0 @@ -.\" sha1.doc - -*- Indented-Text -*- created at: Thu May 17 06:51:50 JST 2001 - -** SHA1(Class) - -A class to implement the SHA1 Secure Hash Algorithm by NIST (the US' -National Institute of Standards and Technology), described in FIPS PUB -180-1. - -Superclass: Object - -Class Methods: - - new([str]) - sha1([str]) - - Creates a new SHA1 object. If a string argument is given, it - is added to the object. (see update.) - -Methods: - - clone - - Copies the SHA1 object. - - digest - - Returns the SHA1 hash of the added strings as a string of 20 - bytes. - - hexdigest - - Returns the SHA1 hash of the added strings as a string of 40 - hexadecimal digits. This method is equal to: - - def hexdigest - ret = '' - digest.each_byte {|i| ret << sprintf('%02x', i) } - ret - end - - update(str) - << str - - Updates the SHA1 object with string str. Repeated calls are - equivalent to a single call with the concatenation of all the - arguments, i.e. m.update(a); m.update(b) is equivalent to - m.update(a+b) and m << a << b is equivalent to m << a+b. - -Copyright: - - sha1.c is in the public domain. - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/sha1/sha1.txt.jp b/ext/sha1/sha1.txt.jp deleted file mode 100644 index dc3d2e38cc..0000000000 --- a/ext/sha1/sha1.txt.jp +++ /dev/null @@ -1,56 +0,0 @@ -.\" sha1.doc - -*- Indented-Text -*- created at: Thu May 17 06:51:50 JST 2001 - -** SHA1(クラス) - -FIPS PUB 180-1に記述されているNIST (the US' National Institute of -Standards and Technology) の SHA1 Secure Hash Algorithmを実装するクラス。 - -Superclass: Object - -Class Methods: - - new([str]) - sha1([str]) - - 新しいSHA1オブジェクトを生成する.文字列引数が与えられるとそれ - を追加する(see update)。 - -Methods: - - clone - - SHA1オブジェクトの複製を作る。 - - digest - - 今までに追加した文字列に対するハッシュ値を20バイト長の文字列で - 返す。 - - hexdigest - - 今までに追加した文字列に対するハッシュ値を、ASCIIコードを使って - 16進数の列を示す'18e40e1401eef67e1ae69efab09afb71f87ffb81'のよう - な40文字の文字列にエンコードして返す。Rubyで書くと以下と同じ。 - - def hexdigest - ret = '' - digest.each_byte {|i| ret << sprintf('%02x', i) } - ret - end - - update(str) - << str - - SHA1オブジェクトに文字列を追加する。複数回updateを呼ぶことは文 - 字列を連結してupdateを呼ぶことと等しい。すなわち m.update(a); - m.update(b) は m.update(a+b) と、 m << a << b は m << a+b と - それぞれ等価である。 - -Copyright: - - sha1.c はパブリックドメインである。 - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: -- cgit v1.2.3