Hashlib's API is getting a bit of a facelift. No massive functional changes, just an API that is a bit more clear and concise and has less fluff (and less exposed functions).
The new API have a class-esque appearance with subclasses delimited by underscores, like so:


// Secure RNG functions

// Hash functions

// HMAC functions

// Cipher functions

// Digest functions

It's my hope that the new nomenclature of the functions improves usability as well as the portability of adding new functions to the library.
AES ECB block encryptors and padding functions are no longer exposed given that the exposed cipher methods automatically apply and strip padding, ECB mode is insecure and lacks the side channel resistance measures placed in the exposed methods.

With that out of the way, great progress.
Also I think if you're already copying the function entry points into the hash structure you should expose the routines as part of the struct rather than exposing routines to call those routines.
beckadamtheinventor wrote:
Also I think if you're already copying the function entry points into the hash structure you should expose the routines as part of the struct rather than exposing routines to call those routines.

Well, I actually defined the pointers in the structs as the proper types:


typedef struct _hmac_ctx {
    bool (*init)(void* ctx, const void* key, size_t keylen); 
    void (*update)(void* ctx, const void* data, size_t len);   
    void (*final)(void* ctx, void* output);                 
    union _hmac {           /**< a union of computational states for various hashes */
        sha256hmac_ctx sha256hmac;
    } Hmac;
} hmac_ctx;

So the user is at perfect liberty to use a more procedural format or a more OOP-esque format.


hash_ctx ctx;
if(!hash_init(&ctx, SHA256)) return 1;

// Method 1 (Procedural)
hash_update(&ctx, data, len);
hash_final(&ctx, digest);

// Method 2 (OOP-esque)
ctx.update(&ctx.Hash, data, len);
ctx.final(&ctx.Hash, digest);
// ctx->update/ctx->final if a pointer.

The new update will be out later tonight, or tomorrow, the latest.
If anyone has code for other crypto hash algorithms besides SHA256, feel free to contribute them and I'll add them to the lib.
"Tonight or tomorrow, the latest", he says. Sure thing.
In my defense, I had some difficulty ironing out some bugs.

Update 9.2

AES implementation is reworked. Uses a stateful context that is stream-safe. This does require a user to open two contexts if they need to communicate in both directions. You can also configure the cipher in the init function rather than init'ing it and then editing the fields you want to change.:


aes_ctx ctx;
uint8_t iv[AES_IVSIZE];
uint8_t key[32];

if(!csrand_init()) return 1;
csrand_fill(iv, sizeof iv);
csrand_fill(key, sizeof key);

aes_init(&ctx, key, sizeof key, iv, AES_MODE_CTR | AES_CTR_NONCELEN(12) | AES_CTR_COUNTERLEN(4));

aes_encrypt(&ctx, <msg>, msglen, <msgout>);

Also once you use a context with encrypt or decrypt, a flag is set linking it to that operation. Attempting to use an encrypt-bound context for decryption or via versa returns AES_INVALID_OPERATION.
Update v10.0

The project is getting a bit of a re-organization.
Formerly HASHLIB is being split into a collection of cryptographic libraries. The implementations list will be color-coded as follows:

    Implemented and done
    Optimization in progress
    Timing analysis review needed
    Planned feature, needs further study


    Buffer comparison


    Secure RNG
    AES-128, AES-192, AES-256 CTR & CBC mode
    elliptic curve public key algorithm



The documentation has also been removed from the code and release package and moved to a documentation site using a similar template to the toolchain's: https://acagliano.github.io/cryptx/index.html
Update - v11

CryptX's ENCRYPT library now adds elliptic curve Diffie-Hellman, using the SECT233k1 elliptic curve. Each function of the API (init/secret) takes about 16 seconds to complete.

Special thanks to calc84maniac, Zeroko and to others in SAX and ez80-dev who helped me as I learned both the math and the code to implement the math, and assisted with optimizing them down from their initial run-time of ~50 seconds.

Update - v12.0 rc1

CryptX's ENCRYPT library now adds Galois Counter (GCM) cipher mode to the AES API.
Those of you with some familiarity with encryption will know what this is. For those that do not, it is a cipher mode that generates an authentication tag in addition to the encrypted message that can be sent with the data so that the recipient can be reasonably sure it has not been tampered with. GCM is not the most secure of the authenticated cipher modes, but it was simplest to implement using the existing code-base (which is getting hefty for this library).

The revision adds a few new functions:


aes_error_t cryptx_aes_update_aad(const struct cryptx_aes_ctx* context, void* aad, size_t aad_len);

aes_error_t cryptx_aes_digest(const struct cryptx_aes_ctx* context, uint8_t *digest);

bool cryptx_aes_verify(
            const struct cryptx_aes_ctx* context,
            const void* aad, size_t aad_len,
            const void* ciphertext, size_t ciphertext_len,
            uint8_t *tag);

The latest RC is up. I encourage people to test and report any issues they may find.
12.0 released

With no bugs in AES-GCM reported, it has been merged to stable.
ENCRYPT now officially supports Galois Counter mode encryption and authentication.

Additionally, the ASN.1 API got a remake for a bit more reliability.
Rather than a single call to do everything and output to an array of structures, I wrote it in a way to give the users a bit more control over how the parser looks at data. The new API looks like this:


// initializes the parser to the start of the data
asn1_error_t cryptx_asn1_start(struct cryptx_asn1_context *context, void *asn1_data, size_t len);

// returns the next element found starting at the current parser offset
asn1_error_t cryptx_asn1_decode(
     struct cryptx_asn1_context *context,
     uint8_t **element_data, size_t *element_len,
     uint8_t *tag, uint8_t *flags);

// skips the current element => seeks to next element of same nesting level
asn1_error_t cryptx_asn1_next(struct cryptx_asn1_context *context);

An example of how to use this is shown:


uint8_t asn1_data = { /* some random ASN.1 data here */ };
struct cryptx_asn1_context asn1_state;  // stateful parser context
asn1_error_t err;
uint8_t *ptr;
size_t elem_len; 
uint8_t tag, flags;
// note that the above are reserved variables for the API to update
// initialize the parser. Return if error.
err = cryptx_asn1_start(&asn1_state, asn1_data, sizeof asn1_data);
if(err != ASN1_OK) return;
// loop until END-OF-FILE returned
while(err != ASN1_EOF){
     err = cryptx_asn1_decode(&asn1_state, &ptr, &elem_len, &tag, &flags);
     if(err) sprintf(CEMU_CONSOLE, "Decoder error %u\n", err);
          printf("Object Data, Tag Id: %u, Flags: %u, Size: %u, Addr: %p\n", tag, flags, elem_len, ptr);
          // if the element is PRIMITIVE type, skip to avoid recursing into it
          err = cryptx_asn1_next(&asn1_state);
v 12.1

Another update once again revising the ASN.1 API. Went from 3 functions back to a single one.


asn1_error_t cryptx_asn1_decode(
        void *data_start,
        size_t data_len,
        uint8_t seek_to,
        uint8_t *element_tag,
        size_t *element_len,
        void **element_data);

data_start should be the beginning of the data and data_len should be it's size.
seek_to is the index in an iterable element to return. So if you're decoding a SEQUENCE or SET, passing 2 will return the 2nd (starting at 0) element in the sequence or set. If seek_to doesn't exist or the element is not an iterable element, ASN1_END_OF_FILE is usually returned.

There's also



The return value of form indicates if the element should be an iterable.

There are some new things being worked on. CryptX now supports importing of PKCS#8 formatted public and private keys. It populates a structure with relevant data from the file it imports.


pkcs_error_t cryptx_pkcs8_import_publickey(const void *data, size_t len, struct cryptx_pkcs8_pubkeyinfo *keyinfo);

pkcs_error_t cryptx_pkcs8_import_privatekey(const void *data, size_t len, struct cryptx_pkcs8_privkeyinfo *keyinfo);

There is no support for encrypted private keys yet.

The functionality of this module is such that you can generate an RSA or EC_SECT233K1 key with, say, openssl on your computer, then take the resulting PEM file, convbin it to an 8xp, send it to your calculator, and then import it with this module.
It searches for the banners (ex: -----BEGIN PUBLIC KEY-----), then strips the banners, then decodes the PEM-encoding, then decodes the DER formatting. You can then access the key data by accessing the structure members directly, or just pass the whole structure directly to the next thing I'll be working on.... TLS.

Passphrase-keyfiles will be implemented soon, but I may work on TLS first. Not sure. Honestly, TLS intimidates me to start. I'm procrastinating.

Current PKCS documentation: https://acagliano.github.io/cryptx/modules/pkcs8.html
I have a somber and yet also exciting announcement to make.
At long last CryptX development is complete. Plans for TLS are being cancelled in favor of moving that into lwIP through the inclusion of mbedtls, and so no further major functional additions or releases are planned apart from bug-fixes and optimizations.

Library Documentation and Final Release link: https://acagliano.github.io/cryptx/
While lwIP will provide a TLS extension (when done), CryptX will remain available for application level security.

Please continue to report any issues as they arise.
I would like to again thank the awesome members of this community for their support and feedback and the direct assistance of several: commandblockguy, beckadamtheinventor, calc84maniac, Zeroko, jacobly, Mateo, and any others I may have neglected to mention. Without your help, I doubt this would have gone anywhere.

Edit: planned changes
- ECDSA sign
- SHA1 bugfixes
These will be announced when done but will be considered a "bugfix" not a release.
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 2 of 2
» All times are UTC - 5 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum