summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-05-16 22:07:28 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2001-05-16 22:07:28 +0000
commit5348fd7d4afcc2ff5e3dba1bddc9fa50a3fb6ddd (patch)
treed41d9d8aa771f88e03aa78f63ebad3bf591bf9c1 /ext
parent4202ff1a9fba06137f58c0c757ada7e5c11b3ac5 (diff)
Initial revision
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1405 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/sha1/extconf.rb15
-rw-r--r--ext/sha1/sha1-ruby.c101
-rw-r--r--ext/sha1/sha1.c173
-rw-r--r--ext/sha1/sha1.h33
-rw-r--r--ext/sha1/sha1.txt50
5 files changed, 372 insertions, 0 deletions
diff --git a/ext/sha1/extconf.rb b/ext/sha1/extconf.rb
new file mode 100644
index 0000000000..0a293e1248
--- /dev/null
+++ b/ext/sha1/extconf.rb
@@ -0,0 +1,15 @@
+require 'mkmf'
+
+i = 0x01020304
+
+case [i].pack('l')
+ when [i].pack('V')
+ $CFLAGS += " -DLITTLE_ENDIAN"
+ when [i].pack('N')
+ $CFLAGS += " -DBIG_ENDIAN"
+ else
+ p "Sorry, your machine has an unusual byte order which is not supported."
+ exit!
+end
+
+create_makefile('sha1')
diff --git a/ext/sha1/sha1-ruby.c b/ext/sha1/sha1-ruby.c
new file mode 100644
index 0000000000..394ebf7c16
--- /dev/null
+++ b/ext/sha1/sha1-ruby.c
@@ -0,0 +1,101 @@
+#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[33];
+ 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_new(argc, argv, class)
+ int argc;
+ VALUE* argv;
+ VALUE class;
+{
+ VALUE arg, obj;
+ SHA1_CTX *sha1;
+
+ rb_scan_args(argc, argv, "01", &arg);
+ if (!NIL_P(arg)) Check_Type(arg, T_STRING);
+
+ obj = Data_Make_Struct(class, SHA1_CTX, 0, free, sha1);
+ rb_obj_call_init(obj, argc, argv);
+ SHA1Init(sha1);
+ if (!NIL_P(arg)) {
+ sha1_update(obj, arg);
+ }
+
+ 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, "<<", sha1_update, 1);
+ rb_define_method(cSHA1, "digest", sha1_digest, 0);
+ rb_define_method(cSHA1, "hexdigest", sha1_hexdigest, 0);
+ rb_define_method(cSHA1, "clone", sha1_clone, 0);
+}
diff --git a/ext/sha1/sha1.c b/ext/sha1/sha1.c
new file mode 100644
index 0000000000..afcc297cb4
--- /dev/null
+++ b/ext/sha1/sha1.c
@@ -0,0 +1,173 @@
+/*
+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 LITTLE_ENDIAN * This should be #define'd if true. */
+/* #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 LITTLE_ENDIAN
+#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 used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void
+SHA1Transform(state, buffer)
+ unsigned long state[5];
+ unsigned char buffer[64];
+{
+unsigned long a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ unsigned long l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void
+SHA1Init(context)
+ SHA1_CTX* context;
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void
+SHA1Update(context, data, len)
+ SHA1_CTX* context;
+ unsigned char* data;
+ unsigned int len;
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void
+SHA1Final(digest, context)
+ unsigned char digest[20];
+ SHA1_CTX* context;
+{
+unsigned long i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
diff --git a/ext/sha1/sha1.h b/ext/sha1/sha1.h
new file mode 100644
index 0000000000..f988476a1b
--- /dev/null
+++ b/ext/sha1/sha1.h
@@ -0,0 +1,33 @@
+#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 */
diff --git a/ext/sha1/sha1.txt b/ext/sha1/sha1.txt
new file mode 100644
index 0000000000..24bf0d4244
--- /dev/null
+++ b/ext/sha1/sha1.txt
@@ -0,0 +1,50 @@
+Class SHA1
+
+ 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:
+
+ README and sha1-ruby.c are derived from the Ruby source and so fall
+ under the same license as Ruby. The rest of this package is in the
+ public domain.