summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-08-23 23:06:09 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-08-23 23:06:09 -0700
commit8a10829e5e35e5b0721260e0a7b31554ec21d766 (patch)
tree037c9464dc75ff36bbfadd0c2f1117fa60b28d75
parent27a722e96f281974e9f49887e9470422dcb1da91 (diff)
downloadtxr-8a10829e5e35e5b0721260e0a7b31554ec21d766.tar.gz
txr-8a10829e5e35e5b0721260e0a7b31554ec21d766.tar.bz2
txr-8a10829e5e35e5b0721260e0a7b31554ec21d766.zip
New state-object-based sha256 and md5 digesting.
* chksum.c (sha256_ctx_s, md5_ctx_s): New symbol variables. (sha256_ops, md5_ops): New static structs. (sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash, md5_end): New functions. (chksum_init): New symbol variables initialized; sha256-begin, sha256-hash, sha256-end, md5-begin, md5-hash, md5-end intrinsics registered. * chksum.h (sha256_begin, sha256_hash, sha256_end, md5_begin, md5_hash, md5_end): Declared. * txr.1: Documented.
-rw-r--r--chksum.c112
-rw-r--r--chksum.h6
-rw-r--r--txr.1112
3 files changed, 230 insertions, 0 deletions
diff --git a/chksum.c b/chksum.c
index 6d65a203..776fe3d1 100644
--- a/chksum.c
+++ b/chksum.c
@@ -48,6 +48,8 @@
#include "chksums/md5.h"
#include "chksum.h"
+static val sha256_ctx_s, md5_ctx_s;
+
static void sha256_stream_impl(val stream, val nbytes, unsigned char *hash)
{
SHA256_t s256;
@@ -165,6 +167,57 @@ val sha256(val obj, val buf_in)
}
}
+static struct cobj_ops sha256_ops = cobj_ops_init(cobj_equal_handle_op,
+ cobj_print_op,
+ cobj_destroy_free_op,
+ cobj_mark_op,
+ cobj_handle_hash_op);
+val sha256_begin(void)
+{
+ SHA256_t *ps256 = coerce(SHA256_t *, chk_malloc(sizeof *ps256));
+ SHA256_init(ps256);
+ return cobj(coerce(mem_t *, ps256), sha256_ctx_s, &sha256_ops);
+}
+
+val sha256_hash(val ctx, val obj)
+{
+ val self = lit("sha256-hash");
+ SHA256_t *ps256 = coerce(SHA256_t *, cobj_handle(self, ctx, sha256_ctx_s));
+
+ switch (type(obj)) {
+ case STR:
+ case LSTR:
+ case LIT:
+ {
+ char *str = utf8_dup_to(c_str(obj));
+ SHA256_update(ps256, coerce(const unsigned char *, str), strlen(str));
+ free(str);
+ }
+ break;
+ case BUF:
+ SHA256_update(ps256, obj->b.data, c_unum(obj->b.len));
+ break;
+ default:
+ uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
+ self, obj, nao);
+ }
+
+ return obj;
+}
+
+val sha256_end(val ctx, val buf_in)
+{
+ val self = lit("sha256-end");
+ unsigned char *hash;
+ SHA256_t *ps256 = coerce(SHA256_t *, cobj_handle(self, ctx, sha256_ctx_s));
+ val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA256_DIGEST_LENGTH),
+ &hash, lit("SHA-256"));
+
+ SHA256_final(ps256, hash);
+ SHA256_init(ps256);
+ return buf;
+}
+
val crc32_stream(val stream, val nbytes)
{
u32_t crc = 0;
@@ -351,12 +404,71 @@ val md5(val obj, val buf_in)
}
}
+static struct cobj_ops md5_ops = cobj_ops_init(cobj_equal_handle_op,
+ cobj_print_op,
+ cobj_destroy_free_op,
+ cobj_mark_op,
+ cobj_handle_hash_op);
+val md5_begin(void)
+{
+ MD5_t *pmd5 = coerce(MD5_t *, chk_malloc(sizeof *pmd5));
+ MD5_init(pmd5);
+ return cobj(coerce(mem_t *, pmd5), md5_ctx_s, &md5_ops);
+}
+
+val md5_hash(val ctx, val obj)
+{
+ val self = lit("md5-hash");
+ MD5_t *pmd5 = coerce(MD5_t *, cobj_handle(self, ctx, md5_ctx_s));
+
+ switch (type(obj)) {
+ case STR:
+ case LSTR:
+ case LIT:
+ {
+ char *str = utf8_dup_to(c_str(obj));
+ MD5_update(pmd5, coerce(const unsigned char *, str), strlen(str));
+ free(str);
+ }
+ break;
+ case BUF:
+ MD5_update(pmd5, obj->b.data, c_unum(obj->b.len));
+ break;
+ default:
+ uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
+ self, obj, nao);
+ }
+
+ return obj;
+}
+
+val md5_end(val ctx, val buf_in)
+{
+ val self = lit("md5-end");
+ unsigned char *hash;
+ MD5_t *pmd5 = coerce(MD5_t *, cobj_handle(self, ctx, md5_ctx_s));
+ val buf = chksum_ensure_buf(self, buf_in, num_fast(MD5_DIGEST_LENGTH),
+ &hash, lit("SHA-256"));
+
+ MD5_final(pmd5, hash);
+ MD5_init(pmd5);
+ return buf;
+}
+
void chksum_init(void)
{
+ sha256_ctx_s = intern(lit("sha256-ctx"), user_package);
+ md5_ctx_s = intern(lit("md5-ctx"), user_package);
reg_fun(intern(lit("sha256-stream"), user_package), func_n3o(sha256_stream, 1));
reg_fun(intern(lit("sha256"), user_package), func_n2o(sha256, 1));
+ reg_fun(intern(lit("sha256-begin"), user_package), func_n0(sha256_begin));
+ reg_fun(intern(lit("sha256-hash"), user_package), func_n2(sha256_hash));
+ reg_fun(intern(lit("sha256-end"), user_package), func_n2o(sha256_end, 1));
reg_fun(intern(lit("crc32-stream"), user_package), func_n2o(crc32_stream, 1));
reg_fun(intern(lit("crc32"), user_package), func_n1(crc32));
reg_fun(intern(lit("md5-stream"), user_package), func_n3o(md5_stream, 1));
reg_fun(intern(lit("md5"), user_package), func_n2o(md5, 1));
+ reg_fun(intern(lit("md5-begin"), user_package), func_n0(md5_begin));
+ reg_fun(intern(lit("md5-hash"), user_package), func_n2(md5_hash));
+ reg_fun(intern(lit("md5-end"), user_package), func_n2o(md5_end, 1));
}
diff --git a/chksum.h b/chksum.h
index 089d784e..6c5f1312 100644
--- a/chksum.h
+++ b/chksum.h
@@ -27,8 +27,14 @@
val sha256_stream(val stream, val nbytes, val buf);
val sha256(val obj, val buf);
+val sha256_begin(void);
+val sha256_hash(val ctx, val obj);
+val sha256_end(val ctx, val buf);
val crc32_stream(val stream, val nbytes);
val crc32(val obj);
val md5_stream(val stream, val nbytes, val buf);
val md5(val obj, val buf_in);
+val md5_begin(void);
+val md5_hash(val ctx, val obj);
+val md5_end(val ctx, val buf);
void chksum_init(void);
diff --git a/txr.1 b/txr.1
index d812274a..b8b7c120 100644
--- a/txr.1
+++ b/txr.1
@@ -52382,6 +52382,118 @@ argument is specified, it must be a buffer that is at least 16 bytes long
in the case of MD5, and at least 32 bytes long in the case of SHA-256.
The hash is placed into that buffer, which is then returned.
+.coNP Functions @, sha256-begin @ sha256-hash and @ sha256-end
+.synb
+.mets (sha256-begin)
+.mets (sha256-hash < ctx << obj )
+.mets (sha256-end < ctx <> [ buf ])
+.syne
+.desc
+The three functions
+.codn sha256-begin ,
+.code sha256-hash
+and
+.code sha256-end
+implement a stateful computation of SHA256 digest which allows multiple input
+sources to contribute to the result. Furthermore, the context object may be
+serially re-used for calculating multiple digests.
+
+The
+.code sha256-begin
+function, which takes no arguments, returns a new SHA256 digest-producing
+context object.
+
+The
+.code sha256-hash
+updates the state of the SHA256 digest object
+.meta ctx
+by including
+.meta obj
+into the digest calculation. The
+.meta obj
+argument may be a character string, whose UTF-8 representation is digested,
+or a buffer object, whose contents are digested.
+The
+.code sha256-hash
+function may be called multiple times to include any mixture of
+strings and buffers into the digest calculation.
+
+The
+.code sha256-end
+function finalizes the digest calculation and returns the digest in
+a buffer. If the
+.meta buf
+argument is omitted, then a new 32-byte buffer is created for this
+purpose. Otherwise,
+.meta buf
+must specify a
+.code buf
+object that is at least 32 bytes long. The digest is stored into this
+buffer and that the buffer is returned.
+
+The
+.code sha256-end
+function additionally resets the
+.meta ctx
+object into the initial state of a newly created context object, so
+that it may be used for another digest session.
+
+.coNP Functions @, md5-begin @ md5-hash and @ md5-end
+.synb
+.mets (md5-begin)
+.mets (md5-hash < ctx << obj )
+.mets (md5-end < ctx <> [ buf ])
+.syne
+.desc
+The three functions
+.codn md5-begin ,
+.code md5-hash
+and
+.code md5-end
+implement a stateful computation of MD5 digest which allows multiple input
+sources to contribute to the result. Furthermore, the context object may be
+serially re-used for calculating multiple digests.
+
+The
+.code md5-begin
+function, which takes no arguments, returns a new MD5 digest-producing
+context object.
+
+The
+.code md5-hash
+updates the state of the MD5 digest object
+.meta ctx
+by including
+.meta obj
+into the digest calculation. The
+.meta obj
+argument may be a character string, whose UTF-8 representation is digested,
+or a buffer object, whose contents are digested.
+The
+.code md5-hash
+function may be called multiple times to include any mixture of
+strings and buffers into the digest calculation.
+
+The
+.code md5-end
+function finalizes the digest calculation and returns the digest in
+a buffer. If the
+.meta buf
+argument is omitted, then a new 16-byte buffer is created for this
+purpose. Otherwise,
+.meta buf
+must specify a
+.code buf
+object that is at least 16 bytes long. The digest is stored into this
+buffer and that the buffer is returned.
+
+The
+.code md5-end
+function additionally resets the
+.meta ctx
+object into the initial state of a newly created context object, so
+that it may be used for another digest session.
+
.SS* The Awk Utility
The \*(TL library provides a macro called