blob: 01c9761577425d6a4cddefa6337b30f137134fdb [file] [log] [blame] [raw]
/*
copyright: Boaz segev, 2016
license: MIT
Feel free to copy, use and enjoy according to the license provided.
*/
#ifndef HTTP_SHA1_BASE64_H
#define HTTP_SHA1_BASE64_H
#include <stdlib.h>
#include <stdint.h>
/** \file
The MiniCrypt library supplies the following, basic, cryptographic functions:
- SHA-1 hashing (considered less secure, use SHA-2/SHA-3 instead).
- SHA-2 hashing
- SHA-3 hashing (on the wish list)
Non-cryptographic, but related, algorithms also supported are:
- Base64 encoding/decoding (non cryptographic, but often used in relation).
The following is a list of Hashing and Encryption methods that should be avoided
and (unless required for some of my projects, such as for websockets), will NOT
be supported:
- SHA-1 (Used for Websockets, but is better avoided).
- RC4
- MD5
All functions will be available under the MiniCrypt global object, i.e.:
char buffer[13] = {0};
MiniCrypt.base64_encode(buffer, "My String", 9);
*/
/*******************************************************************************
Helper types / structs
*/
/**
SHA-1 hashing container - you should ignore the contents of this struct.
The `sha1_s` type will contain all the sha1 data required to perform the
hashing, managing it's encoding. If it's stack allocated, no freeing will be
required.
Use, for example:
#include "mini-crypt.h"
sha1_s sha1;
MiniCrypt.sha1_init(&sha1);
MiniCrypt.sha1_write(&sha1,
"The quick brown fox jumps over the lazy dog", 43);
char *hashed_result = MiniCrypt.sha1_result(&sha1);
*/
typedef struct {
union {
uint32_t i[80];
unsigned char str[64];
} buffer;
union {
uint64_t i;
unsigned char str[8];
} msg_length;
union {
uint32_t i[5];
char str[21];
} digest;
unsigned buffer_pos : 6;
unsigned initialized : 1;
unsigned finalized : 1;
} sha1_s;
/**
SHA-2 function variants.
This enum states the different SHA-2 function variants. placing SHA_512 at the
beginning is meant to set this variant as the default (in case a 0 is passed).
*/
typedef enum {
SHA_512 = 0,
SHA_512_256,
SHA_512_224,
SHA_384,
SHA_256,
SHA_224,
} sha2_variant;
/**
SHA-2 hashing container - you should ignore the contents of this struct.
The `sha2_s` type will contain all the SHA-2 data required to perform the
hashing, managing it's encoding. If it's stack allocated, no freeing will be
required.
Use, for example:
#include "mini-crypt.h"
sha2_s sha2;
MiniCrypt.sha2_init(&sha2, SHA_512);
MiniCrypt.sha2_write(&sha2,
"The quick brown fox jumps over the lazy dog", 43);
char *hashed_result = MiniCrypt.sha2_result(&sha2);
*/
typedef struct {
union {
uint32_t i32[8];
uint64_t i64[8];
char str[65]; /* added 64+1 for the NULL byte.*/
} digest;
union {
uint32_t i32[16];
uint64_t i64[16];
char str[128];
} buffer;
/* notice: we're counting bits, not bytes. max length: 2^128 bits */
union {
__uint128_t i;
char str[16];
} msg_length;
unsigned buffer_pos : 7;
unsigned initialized : 1;
unsigned finalized : 1;
sha2_variant type : 3;
unsigned type_512 : 1;
} sha2_s;
/*******************************************************************************
API Gateway (the MiniCrypt global object)
*/
/**
The MiniCrypt global object (member of the struct MiniCrypt__API___) is the API
namespace gateway fot the MiniCrypt library.
For example:
#include "mini-crypt.h"
sha2_s sha2;
MiniCrypt.sha2_init(&sha2, SHA_512);
MiniCrypt.sha2_write(&sha2,
"The quick brown fox jumps over the lazy dog", 43);
char *hashed_result = MiniCrypt.sha2_result(&sha2);
*/
extern struct MiniCrypt__API___ {
/*****************************************************************************
SHA-1 hashing
*/
/**
Initialize or reset the `sha1` object. This must be performed before hashing
data using sha1.
*/
void (*sha1_init)(sha1_s*);
/**
Writes data to the sha1 buffer.
*/
int (*sha1_write)(sha1_s* s, const char* data, size_t len);
/**
Finalizes the SHA1 hash, returning the Hashed data.
`sha1_result` can be called for the same object multiple times, but the
finalization will only be performed the first time this function is called.
*/
char* (*sha1_result)(sha1_s* s);
/*****************************************************************************
SHA-2 hashing
*/
/**
Initialize/reset the SHA-2 object.
SHA-2 is actually a family of functions with different variants. When
initializing the SHA-2 container, you must select the variant you intend to
apply. The following are valid options (see the sha2_variant enum):
- SHA_512 (== 0)
- SHA_384
- SHA_512_224
- SHA_512_256
- SHA_256
- SHA_224
*/
void (*sha2_init)(sha2_s* s, sha2_variant variant);
/**
Writes data to the SHA-2 buffer.
*/
int (*sha2_write)(sha2_s* s, const char* data, size_t len);
/**
Finalizes the SHA-2 hash, returning the Hashed data.
`sha2_result` can be called for the same object multiple times, but the
finalization will only be performed the first time this function is called.
*/
char* (*sha2_result)(sha2_s* s);
/*****************************************************************************
Base64 encoding
*/
/**
This will encode a byte array (data) of a specified length (len) and
place the encoded data into the target byte buffer (target). The target buffer
MUST have enough room for the expected data.
Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
the raw data's length isn't devisable by 3.
Always assume the target buffer should have room enough for (len*4/3 + 4)
bytes.
Returns the number of bytes actually written to the target buffer
(including the Base64 required padding and excluding a NULL terminator).
A NULL terminator char is NOT written to the target buffer.
*/
int (*base64_encode)(char* target, const char* data, int len);
/**
This will decode a Base64 encoded string of a specified length (len) and
place the decoded data into the target byte buffer (target).
The target buffer MUST have enough room for the expected data.
A NULL byte will be appended to the target buffer. The function will return
the number of bytes written to the target buffer.
If the target buffer is NULL, the encoded string will be destructively edited
and the decoded data will be placed in the original string's buffer.
Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
the raw data's length isn't devisable by 3. Hence, the target buffer should
be, at least, `base64_len/4*3 + 3` long.
Returns the number of bytes actually written to the target buffer (excluding
the NULL terminator byte).
*/
int (*base64_decode)(char* target, char* encoded, int base64_len);
} MiniCrypt;
/* end include gate */
#endif