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:
parent
6ecd6fe37b
commit
76d7dae26a
58 changed files with 3555 additions and 781 deletions
60
LEGAL
60
LEGAL
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
Makefile
|
||||
mkmf.log
|
11
ext/digest/MANIFEST
Normal file
11
ext/digest/MANIFEST
Normal 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
34
ext/digest/defs.h
Normal 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
331
ext/digest/digest.c
Normal 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
32
ext/digest/digest.h
Normal 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
113
ext/digest/digest.txt
Normal 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
111
ext/digest/digest.txt.jp
Normal 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
6
ext/digest/extconf.rb
Normal 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
14
ext/digest/lib/md5.rb
Normal 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
14
ext/digest/lib/sha1.rb
Normal 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
|
|
@ -1 +1,2 @@
|
|||
Makefile
|
||||
mkmf.log
|
4
ext/digest/md5/MANIFEST
Normal file
4
ext/digest/md5/MANIFEST
Normal file
|
@ -0,0 +1,4 @@
|
|||
extconf.rb
|
||||
md5.c
|
||||
md5.h
|
||||
md5init.c
|
19
ext/digest/md5/extconf.rb
Normal file
19
ext/digest/md5/extconf.rb
Normal 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")
|
|
@ -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;
|
||||
}
|
|
@ -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
34
ext/digest/md5/md5init.c
Normal 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));
|
||||
}
|
2
ext/digest/rmd160/.cvsignore
Normal file
2
ext/digest/rmd160/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
Makefile
|
||||
mkmf.log
|
5
ext/digest/rmd160/MANIFEST
Normal file
5
ext/digest/rmd160/MANIFEST
Normal file
|
@ -0,0 +1,5 @@
|
|||
extconf.rb
|
||||
rmd160.c
|
||||
rmd160.h
|
||||
rmd160hl.c
|
||||
rmd160init.c
|
20
ext/digest/rmd160/extconf.rb
Normal file
20
ext/digest/rmd160/extconf.rb
Normal 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
464
ext/digest/rmd160/rmd160.c
Normal 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 **********************/
|
55
ext/digest/rmd160/rmd160.h
Normal file
55
ext/digest/rmd160/rmd160.h
Normal 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_ */
|
96
ext/digest/rmd160/rmd160hl.c
Normal file
96
ext/digest/rmd160/rmd160hl.c
Normal 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));
|
||||
}
|
34
ext/digest/rmd160/rmd160init.c
Normal file
34
ext/digest/rmd160/rmd160init.c
Normal 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));
|
||||
}
|
2
ext/digest/sha1/.cvsignore
Normal file
2
ext/digest/sha1/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
Makefile
|
||||
mkmf.log
|
5
ext/digest/sha1/MANIFEST
Normal file
5
ext/digest/sha1/MANIFEST
Normal file
|
@ -0,0 +1,5 @@
|
|||
extconf.rb
|
||||
sha1.c
|
||||
sha1.h
|
||||
sha1hl.c
|
||||
sha1init.c
|
20
ext/digest/sha1/extconf.rb
Normal file
20
ext/digest/sha1/extconf.rb
Normal 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
283
ext/digest/sha1/sha1.c
Normal 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
37
ext/digest/sha1/sha1.h
Normal 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
102
ext/digest/sha1/sha1hl.c
Normal 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));
|
||||
}
|
34
ext/digest/sha1/sha1init.c
Normal file
34
ext/digest/sha1/sha1init.c
Normal 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));
|
||||
}
|
2
ext/digest/sha2/.cvsignore
Normal file
2
ext/digest/sha2/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
Makefile
|
||||
mkmf.log
|
5
ext/digest/sha2/MANIFEST
Normal file
5
ext/digest/sha2/MANIFEST
Normal file
|
@ -0,0 +1,5 @@
|
|||
extconf.rb
|
||||
sha2.c
|
||||
sha2.h
|
||||
sha2hl.c
|
||||
sha2init.c
|
20
ext/digest/sha2/extconf.rb
Normal file
20
ext/digest/sha2/extconf.rb
Normal 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
937
ext/digest/sha2/sha2.c
Normal 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
107
ext/digest/sha2/sha2.h
Normal 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
252
ext/digest/sha2/sha2hl.c
Normal 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);
|
||||
}
|
47
ext/digest/sha2/sha2init.c
Normal file
47
ext/digest/sha2/sha2init.c
Normal 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
100
ext/digest/test.rb
Normal 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
27
ext/digest/test.sh
Normal 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
|
|
@ -1,8 +0,0 @@
|
|||
MANIFEST
|
||||
depend
|
||||
extconf.rb
|
||||
md5.txt
|
||||
md5.txt.jp
|
||||
md5.h
|
||||
md5c.c
|
||||
md5init.c
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
require 'mkmf'
|
||||
$CFLAGS += " -DHAVE_CONFIG_H"
|
||||
create_makefile('md5')
|
|
@ -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:
|
|
@ -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:
|
|
@ -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);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
MANIFEST
|
||||
extconf.rb
|
||||
sha1-ruby.c
|
||||
sha1.c
|
||||
sha1.h
|
||||
sha1.txt
|
||||
sha1.txt.jp
|
|
@ -1,3 +0,0 @@
|
|||
require 'mkmf'
|
||||
|
||||
create_makefile('sha1')
|
|
@ -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);
|
||||
}
|
172
ext/sha1/sha1.c
172
ext/sha1/sha1.c
|
@ -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
|
||||
}
|
|
@ -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 */
|
|
@ -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:
|
|
@ -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:
|
Loading…
Reference in a new issue