1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
knu 2001-07-13 20:06:14 +00:00
parent 6ecd6fe37b
commit 76d7dae26a
58 changed files with 3555 additions and 781 deletions

60
LEGAL
View file

@ -118,7 +118,7 @@ missing/strftime.c:
missing/strncasecmp.c:
missing/strstr.c:
missing/strtol.c:
ext/sha1/sha1.[ch]:
ext/digest/sha1/sha1.[ch]:
These files are all under public domain.
@ -199,8 +199,7 @@ missing/vsnprintf.c:
From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
paragraph 3 above is now null and void.
ext/md5/md5c.c:
ext/md5/md5.h:
ext/digest/md5/md5.[ch]:
These files are under the following license. Ruby uses modified
versions of them.
@ -226,6 +225,59 @@ ext/md5/md5.h:
L. Peter Deutsch
ghost@aladdin.com
ext/digest/rmd160/rmd160.[ch]:
These files have the following copyright information, and by the
author we are allowed to use it under the new-style BSD license.
AUTHOR: Antoon Bosselaers, ESAT-COSIC
(Arranged for libc by Todd C. Miller)
DATE: 1 March 1996
Copyright (c) Katholieke Universiteit Leuven
1996, All Rights Reserved
ext/digest/rmd160/rmd160hl.c:
ext/digest/sha1/sha1hl.c:
These files are under the beer-ware license.
"THE BEER-WARE LICENSE" (Revision 42):
<phk@login.dkuug.dk> 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
ext/digest/sha2/sha2.[ch]:
ext/digest/sha2/sha2hl.c:
These files are under the new-style BSD license.
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.
ext/nkf/nkf1.7/nkf.c:
This file is under the following license. So to speak, it is
@ -243,7 +295,7 @@ ext/socket/addrinfo.h:
ext/socket/getaddrinfo.c:
ext/socket/getnameinfo.c:
These files are under the BSD license.
These files are under the new-style BSD license.
Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
All rights reserved.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1 +1,2 @@
Makefile
mkmf.log

11
ext/digest/MANIFEST Normal file
View file

@ -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

34
ext/digest/defs.h Normal file
View file

@ -0,0 +1,34 @@
/* -*- C -*-
* $Id$
*/
#ifndef DEFS_H
#define DEFS_H
#include "ruby.h"
#include <sys/types.h>
#if defined(HAVE_SYS_CDEFS_H)
# include <sys/cdefs.h>
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
#if defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#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 */

331
ext/digest/digest.c Normal file
View file

@ -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");
}

32
ext/digest/digest.h Normal file
View file

@ -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;

113
ext/digest/digest.txt Normal file
View file

@ -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:

111
ext/digest/digest.txt.jp Normal file
View file

@ -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:

6
ext/digest/extconf.rb Normal file
View file

@ -0,0 +1,6 @@
# $RoughId: extconf.rb,v 1.6 2001/07/13 15:38:27 knu Exp $
# $Id$
require "mkmf"
create_makefile("digest")

14
ext/digest/lib/md5.rb Normal file
View file

@ -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

14
ext/digest/lib/sha1.rb Normal file
View file

@ -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

View file

@ -1 +1,2 @@
Makefile
mkmf.log

4
ext/digest/md5/MANIFEST Normal file
View file

@ -0,0 +1,4 @@
extconf.rb
md5.c
md5.h
md5init.c

19
ext/digest/md5/extconf.rb Normal file
View file

@ -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")

View file

@ -21,7 +21,7 @@
ghost@aladdin.com
*/
/*$Id$ */
/*
Independent implementation of MD5 (RFC 1321).
@ -41,6 +41,10 @@
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
@ -65,14 +69,14 @@ main()
int i;
for (i = 0; i < 7*2; i += 2) {
md5_state_t state;
md5_byte_t digest[16];
MD5_CTX state;
uint8_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);
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]);
@ -113,7 +117,10 @@ main()
/*
* End of T computation program.
*/
#define T_MASK ((md5_word_t)~0)
#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
@ -181,41 +188,38 @@ main()
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
md5_process(MD5_CTX *pms, const uint8_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;
uint32_t
a = pms->state[0], b = pms->state[1],
c = pms->state[2], d = pms->state[3];
uint32_t t;
#ifndef ARCH_IS_BIG_ENDIAN
# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */
#endif
#if ARCH_IS_BIG_ENDIAN
#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.)
*/
md5_word_t X[16];
const md5_byte_t *xp = data;
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 /* !ARCH_IS_BIG_ENDIAN */
#else
/*
* On little-endian machines, we can process properly aligned data
* without copying it.
*/
md5_word_t xbuf[16];
const md5_word_t *X;
uint32_t xbuf[16];
const uint32_t *X;
if (!((data - (const md5_byte_t *)0) & 3)) {
if (!((data - (const uint8_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
X = (const uint32_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
@ -332,29 +336,29 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
/* 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;
pms->state[0] += a;
pms->state[1] += b;
pms->state[2] += c;
pms->state[3] += d;
}
void
md5_init(md5_state_t *pms)
MD5_Init(MD5_CTX *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;
pms->state[0] = 0x67452301;
pms->state[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->state[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->state[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t 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);
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;
@ -367,14 +371,14 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
memcpy(pms->buffer + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
md5_process(pms, pms->buffer);
}
/* Process full blocks. */
@ -383,28 +387,46 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
memcpy(pms->buffer, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
MD5_Final(uint8_t *digest, MD5_CTX *pms)
{
static const md5_byte_t pad[64] = {
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
};
md5_byte_t data[8];
int i;
uint8_t data[8];
size_t i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
data[i] = (uint8_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);
MD5_Update(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
MD5_Update(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
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;
}

View file

@ -21,7 +21,6 @@
ghost@aladdin.com
*/
/*$Id$ */
/*
Independent implementation of MD5 (RFC 1321).
@ -40,55 +39,37 @@
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/* $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,
* ARCH_IS_BIG_ENDIAN.
* defined, they have the same meaning as in Ghostscript: P1, P2, P3.
*/
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;
uint32_t count[2]; /* message length in bits, lsw first */
uint32_t state[4]; /* digest buffer */
uint8_t buffer[64]; /* accumulate block */
} MD5_CTX;
#ifdef __cplusplus
extern "C"
{
#endif
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));
/* Initialize the algorithm. */
#ifdef P1
void md5_init(P1(md5_state_t *pms));
#else
void md5_init(md5_state_t *pms);
#endif
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
/* 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 */
#endif /* MD5_INCLUDED */

34
ext/digest/md5/md5init.c Normal file
View file

@ -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));
}

View file

@ -0,0 +1,2 @@
Makefile
mkmf.log

View file

@ -0,0 +1,5 @@
extconf.rb
rmd160.c
rmd160.h
rmd160hl.c
rmd160init.c

View file

@ -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")

464
ext/digest/rmd160/rmd160.c Normal file
View file

@ -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 <sys/endian.h>
#endif
#ifdef HAVE_MACHINE_ENDIAN_H_
#include <machine/endian.h>
#endif
/* #include "namespace.h" */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 **********************/

View file

@ -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_ */

View file

@ -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):
* <phk@login.dkuug.dk> 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 <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#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));
}

View file

@ -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));
}

View file

@ -0,0 +1,2 @@
Makefile
mkmf.log

5
ext/digest/sha1/MANIFEST Normal file
View file

@ -0,0 +1,5 @@
extconf.rb
sha1.c
sha1.h
sha1hl.c
sha1init.c

View file

@ -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")

283
ext/digest/sha1/sha1.c Normal file
View file

@ -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 <steve@edmweb.com>
* 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 <sys/param.h>
#include <sys/systm.h>
#define _DIAGASSERT(x) (void)0
#else
/* #include "namespace.h" */
#include <assert.h>
#include <string.h>
#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;
}

37
ext/digest/sha1/sha1.h Normal file
View file

@ -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 <steve@edmweb.com>
* 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_ */

102
ext/digest/sha1/sha1hl.c Normal file
View file

@ -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):
* <phk@login.dkuug.dk> 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 <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#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));
}

View file

@ -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));
}

View file

@ -0,0 +1,2 @@
Makefile
mkmf.log

5
ext/digest/sha2/MANIFEST Normal file
View file

@ -0,0 +1,5 @@
extconf.rb
sha2.c
sha2.h
sha2hl.c
sha2init.c

View file

@ -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")

937
ext/digest/sha2/sha2.c Normal file
View file

@ -0,0 +1,937 @@
/*
* sha2.c
*
* Version 1.0.0beta1
*
* Written by Aaron D. Gifford <me@aarongifford.com>
*
* 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 <stdio.h>
#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
#include <assert.h> /* 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;
}

107
ext/digest/sha2/sha2.h Normal file
View file

@ -0,0 +1,107 @@
/*
* sha2.h
*
* Version 1.0.0beta1
*
* Written by Aaron D. Gifford <me@aarongifford.com>
*
* 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__ */

252
ext/digest/sha2/sha2hl.c Normal file
View file

@ -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 <me@aarongifford.com>
*
* 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 <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#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);
}

View file

@ -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)
}

100
ext/digest/test.rb Normal file
View file

@ -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

27
ext/digest/test.sh Normal file
View file

@ -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

View file

@ -1,8 +0,0 @@
MANIFEST
depend
extconf.rb
md5.txt
md5.txt.jp
md5.h
md5c.c
md5init.c

View file

@ -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

View file

@ -1,3 +0,0 @@
require 'mkmf'
$CFLAGS += " -DHAVE_CONFIG_H"
create_makefile('md5')

View file

@ -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:

View file

@ -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:

View file

@ -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);
}

View file

@ -1,7 +0,0 @@
MANIFEST
extconf.rb
sha1-ruby.c
sha1.c
sha1.h
sha1.txt
sha1.txt.jp

View file

@ -1,3 +0,0 @@
require 'mkmf'
create_makefile('sha1')

View file

@ -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);
}

View file

@ -1,172 +0,0 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
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
}

View file

@ -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 <stdio.h>
#include <string.h>
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 */

View file

@ -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:

View file

@ -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: