Add tests
This commit is contained in:
parent
255d6ad9f1
commit
e19966f329
|
@ -2,3 +2,4 @@
|
|||
*.o
|
||||
*.bundle
|
||||
Makefile
|
||||
test/test_vectors.rb
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
.phony: all clean test
|
||||
|
||||
all: ext/digest/Makefile
|
||||
make -C ext/digest
|
||||
|
||||
ext/digest/Makefile: ext/digest/extconf.rb
|
||||
cd ext/digest && ruby extconf.rb
|
||||
|
||||
clean:
|
||||
if [[ -f ext/digest/Makefile ]]; then make -C ext/digest clean; fi
|
||||
rm -f ext/digest/Makefile
|
||||
rm -f test/test_vectors.rb
|
||||
|
||||
test: all test/test_vectors.rb
|
||||
ruby test/test_all.rb
|
||||
|
||||
test/test_vectors.rb: test/generate_tests.rb test/data/*
|
||||
ruby test/generate_tests.rb > test/test_vectors.rb
|
10
README.md
10
README.md
|
@ -1,6 +1,6 @@
|
|||
# The SHA-3 (Keccak) extension for Ruby
|
||||
|
||||
This Ruby extension implements the SHA-3 (Keccak) cryptographic hashing algorithm. It is based on the reference C implementation, version 3.2. The exposed interface is almost identical to that of the `digest` standard library.
|
||||
This Ruby extension implements the SHA-3 ([Keccak](http://keccak.noekeon.org/)) cryptographic hashing algorithm. It is based on the reference C implementation, version 3.2. The exposed interface is almost identical to that of the `digest` standard library.
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -30,3 +30,11 @@ Keccak supports 5 hash lengths: 224-bit, 256-bit, 384-bit, 512-bit and variable
|
|||
|
||||
# You can pass a hash length to the constructor.
|
||||
digest = Digest::SHA3.new(224)
|
||||
|
||||
## Running the test suite
|
||||
|
||||
Run the test suite as follows:
|
||||
|
||||
make test
|
||||
|
||||
A part of the test suite is automatically generated from Keccak's reference test suite.
|
||||
|
|
|
@ -13,6 +13,7 @@ Gem::Specification.new do |s|
|
|||
s.files = Dir[
|
||||
"README.md",
|
||||
"LICENSE",
|
||||
"Makefile",
|
||||
"digest-sha3.gemspec",
|
||||
"ext/**/*.{c,h,rb}",
|
||||
"lib/**/*"
|
||||
|
|
|
@ -11,9 +11,17 @@ typedef struct {
|
|||
} RbSHA3;
|
||||
|
||||
static VALUE
|
||||
rb_sha3_new(int argc, VALUE *argv, VALUE klass) {
|
||||
rb_sha3_alloc(VALUE klass) {
|
||||
RbSHA3 *ctx;
|
||||
|
||||
ctx = (RbSHA3 *) xmalloc(sizeof(RbSHA3));
|
||||
ctx->bitlen = -1;
|
||||
return Data_Wrap_Struct(klass, 0, xfree, ctx);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_sha3_initialize(int argc, VALUE *argv, VALUE self) {
|
||||
RbSHA3 *ctx;
|
||||
VALUE obj;
|
||||
VALUE hashlen;
|
||||
int i_hashlen;
|
||||
|
||||
|
@ -22,18 +30,16 @@ rb_sha3_new(int argc, VALUE *argv, VALUE klass) {
|
|||
} else {
|
||||
i_hashlen = NUM2INT(hashlen);
|
||||
}
|
||||
|
||||
ctx = (RbSHA3 *) xmalloc(sizeof(RbSHA3));
|
||||
obj = Data_Wrap_Struct(klass, 0, xfree, ctx);
|
||||
ctx->bitlen = i_hashlen;
|
||||
|
||||
if (ctx->bitlen == 0) {
|
||||
if (i_hashlen == 0) {
|
||||
rb_raise(rb_eRuntimeError, "Unsupported hash length");
|
||||
}
|
||||
|
||||
Data_Get_Struct(self, RbSHA3, ctx);
|
||||
ctx->bitlen = i_hashlen;
|
||||
|
||||
switch (Init(&ctx->state, i_hashlen)) {
|
||||
case SUCCESS:
|
||||
return obj;
|
||||
return self;
|
||||
case FAIL:
|
||||
rb_raise(rb_eRuntimeError, "Unknown error");
|
||||
return Qnil;
|
||||
|
@ -47,19 +53,15 @@ rb_sha3_new(int argc, VALUE *argv, VALUE klass) {
|
|||
}
|
||||
|
||||
static VALUE
|
||||
rb_sha3_copy(VALUE copy, VALUE obj) {
|
||||
RbSHA3 *ctx_copy, *ctx_obj;
|
||||
rb_sha3_initialize_copy(VALUE self, VALUE other) {
|
||||
RbSHA3 *ctx_self, *ctx_other;
|
||||
|
||||
Data_Get_Struct(copy, RbSHA3, ctx_copy);
|
||||
Data_Get_Struct(obj, RbSHA3, ctx_obj);
|
||||
if (copy == obj) {
|
||||
return copy;
|
||||
}
|
||||
rb_check_frozen(copy);
|
||||
|
||||
memcpy(&ctx_copy->state, &ctx_obj->state, sizeof(hashState));
|
||||
ctx_copy->bitlen = ctx_obj->bitlen;
|
||||
return copy;
|
||||
rb_check_frozen(self);
|
||||
Data_Get_Struct(self, RbSHA3, ctx_self);
|
||||
Data_Get_Struct(other, RbSHA3, ctx_other);
|
||||
memcpy(&ctx_self->state, &ctx_other->state, sizeof(hashState));
|
||||
ctx_self->bitlen = ctx_other->bitlen;
|
||||
return self;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -123,8 +125,9 @@ void __attribute__((visibility("default")))
|
|||
Init_sha3() {
|
||||
mDigest = rb_define_module("Digest");
|
||||
cSHA3 = rb_define_class_under(mDigest, "SHA3", rb_cObject);
|
||||
rb_define_singleton_method(cSHA3, "new", rb_sha3_new, -1);
|
||||
rb_define_method(cSHA3, "initialize_copy", rb_sha3_copy, 1);
|
||||
rb_define_alloc_func(cSHA3, rb_sha3_alloc);
|
||||
rb_define_method(cSHA3, "initialize", rb_sha3_initialize, -1);
|
||||
rb_define_method(cSHA3, "initialize_copy", rb_sha3_initialize_copy, 1);
|
||||
rb_define_method(cSHA3, "reset", rb_sha3_reset, 0);
|
||||
rb_define_method(cSHA3, "update", rb_sha3_update, 1);
|
||||
rb_define_method(cSHA3, "<<", rb_sha3_update, 1);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
|||
From KeccakKAT-3.zip
|
||||
|
||||
http://keccak.noekeon.org/KeccakKAT-3.zip
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This will generate a test suite.
|
||||
# Based on python-sha3's test suite.
|
||||
|
||||
FILES = [
|
||||
['test/data/ShortMsgKAT_224.txt', 224],
|
||||
['test/data/ShortMsgKAT_256.txt', 256],
|
||||
['test/data/ShortMsgKAT_384.txt', 384],
|
||||
['test/data/ShortMsgKAT_512.txt', 512],
|
||||
['test/data/LongMsgKAT_224.txt', 224],
|
||||
]
|
||||
|
||||
def generate
|
||||
puts %Q{
|
||||
# encoding: binary
|
||||
# This file generated by generate_tests.rb
|
||||
|
||||
require 'test/unit'
|
||||
|
||||
class SHA3Tests < Test::Unit::TestCase
|
||||
}
|
||||
|
||||
FILES.each do |path, hashlen|
|
||||
contents = File.read(path).split('Len = ')
|
||||
contents.each do |test|
|
||||
lines = test.split("\n")
|
||||
if !lines.empty? && lines[0] !~ /^#/
|
||||
length = lines[0].to_i
|
||||
if length % 8 == 0 && length != 0
|
||||
msg_raw = [lines[1].split(' = ').last].pack("H*")
|
||||
md = lines[2].split(' = ').last.downcase
|
||||
name = File.basename(path).split('.')[0]
|
||||
puts %Q{
|
||||
def test_#{name}_#{length}
|
||||
inst = Digest::SHA3.new(#{hashlen})
|
||||
inst.update(#{msg_raw.inspect})
|
||||
assert_equal #{md.inspect}, inst.hexdigest
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
puts "end"
|
||||
end
|
||||
|
||||
generate
|
|
@ -0,0 +1,5 @@
|
|||
$LOAD_PATH.unshift(File.expand_path("lib"))
|
||||
$LOAD_PATH.unshift(File.expand_path("ext"))
|
||||
require 'digest/sha3'
|
||||
require File.expand_path('test/test_usage')
|
||||
require File.expand_path('test/test_vectors')
|
|
@ -0,0 +1,55 @@
|
|||
require 'test/unit'
|
||||
|
||||
class SHA3UsageTest < Test::Unit::TestCase
|
||||
def init(hashsize = 512)
|
||||
@digest = Digest::SHA3.new(hashsize)
|
||||
end
|
||||
|
||||
def test_copy
|
||||
a = init(224)
|
||||
a.update('foo')
|
||||
b = a.dup
|
||||
assert_equal b.digest, a.digest
|
||||
b.update('bar')
|
||||
assert_not_equal b.digest, a.digest
|
||||
end
|
||||
|
||||
def test_class_methods
|
||||
assert_equal 'a9cab59eb40a10b246290f2d6086e32e3689faf1d26b470c899f2802',
|
||||
Digest::SHA3.hexdigest("\xcc", 224)
|
||||
end
|
||||
|
||||
def test_update
|
||||
a = init(224)
|
||||
a.update("\xcc")
|
||||
assert_equal 'a9cab59eb40a10b246290f2d6086e32e3689faf1d26b470c899f2802', a.hexdigest
|
||||
end
|
||||
|
||||
def test_updates
|
||||
a = init(224)
|
||||
a.update("\x21")
|
||||
a.update("\xf1\x34")
|
||||
a.update("\xac\x57")
|
||||
assert_equal '5573da2b02216a860389a581f6e9fb8d805e9e02f6fa911701eee298', a.hexdigest
|
||||
end
|
||||
|
||||
def test_empty_224
|
||||
a = init(224)
|
||||
assert_equal 'f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd', a.hexdigest
|
||||
end
|
||||
|
||||
def test_empty_256
|
||||
a = init(256)
|
||||
assert_equal 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', a.hexdigest
|
||||
end
|
||||
|
||||
def test_empty_384
|
||||
a = init(384)
|
||||
assert_equal '2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff', a.hexdigest()
|
||||
end
|
||||
|
||||
def test_empty_512
|
||||
a = init(512)
|
||||
assert_equal '0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e', a.hexdigest
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue