mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-19 13:49:17 +02:00
The original Scheme implementation is astonishingly slow. Rewriting SHA-2 in C yields around x10000 speed boost for premade strings and bytevectors. For input ports this is alleviated to x100 boost. The implementation is divided into two parts: native computational backend and thin Scheme interface. It is tedious to properly do IO from C, so the Scheme code handles reading data from an input port and the C code performs actual computations on byte buffers (which is also used to handle strings and bytevectors directly). Scheme wrapper reads data in chunked manner with 'read-bytevector'. Currently, the chunk size has insignificant impact on performance as soon as it is bigger than 64. Also, using simply read-bytevector turned out to be 33% faster than preallocating a buffer and filling it with read-bytevector! One tricky part is how to get exact 32-bit integers in C89. We have no <inttypes.h> there, so instead we use <limits.h> to see whether we have a standard type with suitable boundaries. The other one is how to return a properly tagged sha_context from C. Chibi FFI currently cannot handle the case when a procedure returns either a C pointer (which needs to be boxed) or an exception (which should be left as is). To workaround this sexp_start_sha() receives a dummy argument of type sha_context; this makes Chibi FFI to put a proper type tag into 'self', which is then extracted in the C code. This commits adds a new shared library 'crypto$(SO)' with intent to keep there all native code of (chibi crypto) libraries. This allows to simply put any future native implementation of SHA-512 or MD5 in some md5.c and just include those files into crypto.stub.
39 lines
1.5 KiB
Text
39 lines
1.5 KiB
Text
(c-include-verbatim "sha2.c")
|
|
|
|
;; \procedure{(start-sha type)}
|
|
;;
|
|
;; Allocates a new opaque computation context for a SHA-\var{type}
|
|
;; digest, where \var{type} can be one of the following constants:
|
|
;; \scheme{type-sha-224}, \scheme{type-sha-256}.
|
|
|
|
(define-c-struct sha_context)
|
|
|
|
(define-c sexp (start-sha "sexp_start_sha")
|
|
((value ctx sexp) (value self sexp) unsigned-int (value NULL sha_context)))
|
|
|
|
(define-c-const unsigned-int (type-sha-224 "SHA_TYPE_224"))
|
|
(define-c-const unsigned-int (type-sha-256 "SHA_TYPE_256"))
|
|
|
|
;; \procedure{(add-sha-data! sha-context data)}
|
|
;;
|
|
;; Adds a new piece of data into the given context. \var{data} can be
|
|
;; a bytevector or a string. Bytevectors are added as sequences bytes.
|
|
;; Strings are added as sequences of byte representations of their
|
|
;; chars (which is either UTF-8 or ASCII code point sequence, depending
|
|
;; on whether Chibi was compiled with Unicode support).
|
|
;;
|
|
;; It is an error to add more data into a context that was finalized
|
|
;; by \scheme{get-sha}. This procedure returns an unspecified value.
|
|
|
|
(define-c sexp (add-sha-data! "sexp_add_sha_data")
|
|
((value ctx sexp) (value self sexp) sha_context sexp))
|
|
|
|
;; \procedure{(get-sha sha-context)}
|
|
;;
|
|
;; Finalizes computation and returns resulting SHA-2 digest as a hex
|
|
;; string (in lowercase). It is not possible to add more data with
|
|
;; \scheme{add-sha-data!} after this call. Though, digest string can
|
|
;; be retrieved multiple times from the same computation context.
|
|
|
|
(define-c sexp (get-sha "sexp_get_sha")
|
|
((value ctx sexp) (value self sexp) sha_context))
|