commit
12d155bebd
3 changed files with 80 additions and 56 deletions
|
@ -9,6 +9,7 @@ Gem::Specification.new do |s|
|
||||||
s.description = "The SHA-3 (Keccak) hash."
|
s.description = "The SHA-3 (Keccak) hash."
|
||||||
s.authors = ["Hongli Lai (Phusion)", "Keccak authors"]
|
s.authors = ["Hongli Lai (Phusion)", "Keccak authors"]
|
||||||
s.extensions << "ext/digest/extconf.rb"
|
s.extensions << "ext/digest/extconf.rb"
|
||||||
|
s.require_ruby_version = "~> 2.2"
|
||||||
|
|
||||||
s.files = Dir[
|
s.files = Dir[
|
||||||
"README.md",
|
"README.md",
|
||||||
|
|
|
@ -9,19 +9,69 @@
|
||||||
#define MAX_DIGEST_SIZE 64
|
#define MAX_DIGEST_SIZE 64
|
||||||
#define DEFAULT_DIGEST_LEN 512
|
#define DEFAULT_DIGEST_LEN 512
|
||||||
|
|
||||||
static void sha3_init_func(hashState *ctx);
|
static int sha3_init_func(hashState *ctx);
|
||||||
static void sha3_update_func(hashState *ctx, unsigned char *str, size_t len);
|
static void sha3_update_func(hashState *ctx, unsigned char *str, size_t len);
|
||||||
|
static int sha3_finish_func(hashState *ctx, unsigned char *digest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Metadata definition for the SHA3 algorithm.
|
||||||
|
Defines the Version, sizes for block and digest as well as
|
||||||
|
the entry points for the algorithms
|
||||||
|
*/
|
||||||
static rb_digest_metadata_t sha3 = {
|
static rb_digest_metadata_t sha3 = {
|
||||||
RUBY_DIGEST_API_VERSION,
|
RUBY_DIGEST_API_VERSION,
|
||||||
DEFAULT_DIGEST_LEN,
|
DEFAULT_DIGEST_LEN,
|
||||||
KeccakPermutationSize - (2 * DEFAULT_DIGEST_LEN),
|
KeccakPermutationSize - (2 * DEFAULT_DIGEST_LEN), //size of blocks
|
||||||
sizeof(hashState),
|
sizeof(hashState), //size of context for the object we'll be passed in below functions.
|
||||||
(rb_digest_hash_init_func_t)sha3_init_func,
|
(rb_digest_hash_init_func_t)sha3_init_func,
|
||||||
(rb_digest_hash_update_func_t)sha3_update_func,
|
(rb_digest_hash_update_func_t)sha3_update_func,
|
||||||
NULL,
|
(rb_digest_hash_finish_func_t)sha3_finish_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Initialization function for the algorithm,
|
||||||
|
gets called during allocation of the digest object.
|
||||||
|
we override initialize to do custom hash size, so we don't care too much here.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
sha3_init_func(hashState *ctx) {
|
||||||
|
// Just return a 1 ' successful' we override the init function
|
||||||
|
// so this is not necessary
|
||||||
|
// the base class alloc calls this to initialize the algorithm
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update function, take the current context and add str to it */
|
||||||
|
static void
|
||||||
|
sha3_update_func(hashState *ctx, unsigned char *str, size_t len) {
|
||||||
|
Update(ctx, str, len * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish the hash calculation and return the finished string */
|
||||||
|
static int
|
||||||
|
sha3_finish_func(hashState *ctx, unsigned char *digest) {
|
||||||
|
Final(ctx, digest);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ruby method. Digest::SHA3#finish()
|
||||||
|
* No Arguments
|
||||||
|
* @returns [String] Encoded Digest String
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_finish(VALUE self) {
|
||||||
|
hashState *ctx;
|
||||||
|
VALUE digest;
|
||||||
|
|
||||||
|
ctx = (hashState *)RTYPEDDATA_DATA(self);
|
||||||
|
digest = rb_str_new(0, ctx->capacity / 2 / 8);
|
||||||
|
sha3_finish_func(ctx, (unsigned char *)RSTRING_PTR(digest));
|
||||||
|
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* :nodoc: private method
|
||||||
|
* initialize the ctx with the bitlength
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
sha3_init(hashState *ctx, size_t bitlen) {
|
sha3_init(hashState *ctx, size_t bitlen) {
|
||||||
switch (Init(ctx, bitlen)) {
|
switch (Init(ctx, bitlen)) {
|
||||||
|
@ -36,25 +86,10 @@ sha3_init(hashState *ctx, size_t bitlen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* Ruby method. Digest::SHA3.new(hashlen)
|
||||||
sha3_init_func(hashState *ctx) {
|
* @param hashlen The length of hash, only supports 224, 256, 384 or 512
|
||||||
Init(ctx, ctx->capacity / 2);
|
* @returns [Digest::SHA3] new object.
|
||||||
}
|
*/
|
||||||
|
|
||||||
static void
|
|
||||||
sha3_update_func(hashState *ctx, unsigned char *str, size_t len) {
|
|
||||||
Update(ctx, str, len * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
rb_sha3_alloc(VALUE klass) {
|
|
||||||
hashState *ctx;
|
|
||||||
|
|
||||||
ctx = (hashState *) xmalloc(sizeof(hashState));
|
|
||||||
sha3_init(ctx, DEFAULT_DIGEST_LEN);
|
|
||||||
return Data_Wrap_Struct(klass, 0, xfree, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_sha3_initialize(int argc, VALUE *argv, VALUE self) {
|
rb_sha3_initialize(int argc, VALUE *argv, VALUE self) {
|
||||||
hashState *ctx;
|
hashState *ctx;
|
||||||
|
@ -66,46 +101,35 @@ rb_sha3_initialize(int argc, VALUE *argv, VALUE self) {
|
||||||
} else {
|
} else {
|
||||||
i_hashlen = NUM2INT(hashlen);
|
i_hashlen = NUM2INT(hashlen);
|
||||||
}
|
}
|
||||||
switch (i_hashlen) {
|
if ( i_hashlen == 0) {
|
||||||
case 0:
|
|
||||||
rb_raise(rb_eArgError, "Unsupported hash length");
|
rb_raise(rb_eArgError, "Unsupported hash length");
|
||||||
case DEFAULT_DIGEST_LEN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Data_Get_Struct(self, hashState, ctx);
|
|
||||||
sha3_init(ctx, i_hashlen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
ctx = (hashState *)RTYPEDDATA_DATA(self);
|
||||||
}
|
sha3_init(ctx, i_hashlen);
|
||||||
|
|
||||||
static VALUE
|
return rb_call_super(0, NULL);
|
||||||
rb_sha3_finish(VALUE self) {
|
|
||||||
hashState *ctx;
|
|
||||||
VALUE digest;
|
|
||||||
|
|
||||||
Data_Get_Struct(self, hashState, ctx);
|
|
||||||
|
|
||||||
digest = rb_str_new(0, ctx->capacity / 2 / 8);
|
|
||||||
|
|
||||||
Final(ctx, (unsigned char *)RSTRING_PTR(digest));
|
|
||||||
|
|
||||||
return digest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ruby method. Digest::SHA3#digest_length
|
||||||
|
* @returns [Numeric] Length of the digest.
|
||||||
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_sha3_digest_length(VALUE self) {
|
rb_sha3_digest_length(VALUE self) {
|
||||||
hashState *ctx;
|
hashState *ctx;
|
||||||
|
|
||||||
Data_Get_Struct(self, hashState, ctx);
|
ctx = (hashState *)RTYPEDDATA_DATA(self);
|
||||||
return INT2FIX(ctx->capacity / 2 / 8);
|
return INT2FIX(ctx->capacity / 2 / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ruby method. Digest::SHA3#block_length
|
||||||
|
* @returns [Numeric] Length of blocks in this digest.
|
||||||
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_sha3_block_length(VALUE self) {
|
rb_sha3_block_length(VALUE self) {
|
||||||
hashState *ctx;
|
hashState *ctx;
|
||||||
|
|
||||||
Data_Get_Struct(self, hashState, ctx);
|
ctx = (hashState *)RTYPEDDATA_DATA(self);
|
||||||
return INT2FIX(ctx->rate / 8);
|
return INT2FIX(ctx->rate / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,11 +144,10 @@ Init_sha3() {
|
||||||
|
|
||||||
cSHA3 = rb_define_class_under(mDigest, "SHA3", cDigest_Base);
|
cSHA3 = rb_define_class_under(mDigest, "SHA3", cDigest_Base);
|
||||||
|
|
||||||
rb_ivar_set(cSHA3, rb_intern("metadata"), Data_Wrap_Struct(rb_cObject, 0, 0, &sha3));
|
rb_iv_set(cSHA3, "metadata", Data_Wrap_Struct(0, 0, 0, (void *)&sha3));
|
||||||
|
|
||||||
rb_define_alloc_func(cSHA3, rb_sha3_alloc);
|
|
||||||
rb_define_method(cSHA3, "initialize", rb_sha3_initialize, -1);
|
rb_define_method(cSHA3, "initialize", rb_sha3_initialize, -1);
|
||||||
rb_define_private_method(cSHA3, "finish", rb_sha3_finish, 0);
|
|
||||||
rb_define_method(cSHA3, "digest_length", rb_sha3_digest_length, 0);
|
rb_define_method(cSHA3, "digest_length", rb_sha3_digest_length, 0);
|
||||||
rb_define_method(cSHA3, "block_length", rb_sha3_block_length, 0);
|
rb_define_method(cSHA3, "block_length", rb_sha3_block_length, 0);
|
||||||
|
rb_define_method(cSHA3, "finish", rb_sha3_finish, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Digest
|
module Digest
|
||||||
class SHA3
|
class SHA3
|
||||||
module Version
|
module Version
|
||||||
STRING = "1.0.2"
|
STRING = "1.1.0"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in a new issue