Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/GAP/src/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 10 kB image not shown  

Quelle  sha256.c   Sprache: C

 
/****************************************************************************
**
**  This file is part of GAP, a system for computational discrete algebra.
**
**  Copyright of GAP belongs to its developers, whose names are too numerous
**  to list here. Please refer to the COPYRIGHT file for details.
**
**  SPDX-License-Identifier: GPL-2.0-or-later
*/


#include "sha256.h"

#include "bool.h"
#include "error.h"
#include "integer.h"
#include "modules.h"
#include "objects.h"
#include "plist.h"
#include "stringobj.h"

#include "config.h"

#include <string.h>

static Obj GAP_SHA256_State_Type;

// Implements the SHA256 hash function as per the description in
// https://web.archive.org/web/20130526224224/http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
//


// For the moment we assume the input is a string, we should probably have a
// list of bytes, or words or something

static inline UInt4 RotateRight(UInt4 x, const UInt4 n)
{
    return (x >> n) | (x << (32 - n));
}

static inline UInt4 Ch(UInt4 x, UInt4 y, UInt4 z)
{
    return (x & y) ^ (~x & z);
}

static inline UInt4 Maj(UInt4 x, UInt4 y, UInt4 z)
{
    return (x & y) ^ (x & z) ^ (y & z);
}

static inline UInt4 Sigma0(UInt4 x)
{
    return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
}

static inline UInt4 Sigma1(UInt4 x)
{
    return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
}

static inline UInt4 sigma0(UInt4 x)
{
    return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
}

static inline UInt4 sigma1(UInt4 x)
{
    return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
}

static const UInt4 k[] = {
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
    0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
    0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
    0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
    0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
    0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

static const UInt4 rinit[] = {
    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};

#ifdef WORDS_BIGENDIAN
#define be32decode(dst, src, len) memcpy(dst, src, len)
#define be32encode(dst, src, len) memcpy(dst, src, len)
#define store64be(dst, x) *dst = x
#else
static void be32decode(UInt4 * dst, const UInt1 * src, UInt len)
{
    UInt i;
    for (i = 0; i < (len >> 2); i++) {
        dst[i] = (src[i * 4] << 24) | (src[i * 4 + 1] << 16) |
                 (src[i * 4 + 2] << 8) | (src[i * 4 + 3]);
    }
}

static void be32encode(UInt1 * dst, const UInt4 * src, UInt len)
{
    UInt i;
    for (i = 0; i < (len >> 2); i++) {
        dst[4 * i + 0] = (src[i] & 0xff000000) >> 24;
        dst[4 * i + 1] = (src[i] & 0xff0000) >> 16;
        dst[4 * i + 2] = (src[i] & 0xff00) >> 8;
        dst[4 * i + 3] = (src[i] & 0xff);
    }
}

static void store64be(UInt8 * dst, UInt8 x)
{
    *dst = (((x >> 56) | ((x >> 40) & 0xff00) | ((x >> 24) & 0xff0000) |
             ((x >> 8) & 0xff000000) | ((x << 8) & ((UInt8)0xff << 32)) |
             ((x << 24) & ((UInt8)0xff << 40)) |
             ((x << 40) & ((UInt8)0xff << 48)) | ((x << 56))));
}
#endif

typedef struct sha256_state_t {
    UInt4 r[8];       // Current hash value register
    UInt  count;      // Nr of bits already hashed
    UInt1 buf[64];    // One chunk, 512 bits
} sha256_state_t;

static int sha256_init(sha256_state_t * state)
{
    memcpy(state->r, rinit, sizeof(rinit));
    state->count = 0UL;
    memset(state->buf, 0, 64);

    return 0;
}

static void sha256_transform(UInt4       state[8],
                             const UInt1 block[64],
                             UInt4       w[64],
                             UInt4       r[8])
{
    UInt  i;
    UInt4 temp1, temp2;

    memcpy(r, state, 32);
    be32decode(w, block, 64);
    for (i = 16; i < 64; i++) {
        w[i] = sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16];
    }

    // A block is 512bit = 64bytes
    for (i = 0; i < 64; i++) {
        temp1 = r[7] + Sigma1(r[4]) + Ch(r[4], r[5], r[6]) + k[i] + w[i];
        temp2 = Sigma0(r[0]) + Maj(r[0], r[1], r[2]);
        r[7] = r[6];
        r[6] = r[5];
        r[5] = r[4];
        r[4] = r[3] + temp1;
        r[3] = r[2];
        r[2] = r[1];
        r[1] = r[0];
        r[0] = temp1 + temp2;
    }
    for (i = 0; i < 8; i++) {
        state[i] += r[i];
    }
}

static int sha256_update(sha256_state_t * state, const UChar * buf, UInt8 len)
{
    UInt4 i, rem;
    UInt4 w[64];
    UInt4 r[8];

    // If there is buffered stuff in state, fill block
    rem = (state->count >> 3) & 0x3f;
    // Number of bits already hashed. Needed for continuation, and for
    // padding
    state->count += len << 3;

    // Not enough to hash full block, just buffer
    if (len < 64 - rem) {
        for (i = 0; i < len; i++) {
            state->buf[rem + i] = buf[i];
        }
        return 0;
    }
    for (i = 0; i < 64 - rem; i++) {
        state->buf[rem + i] = buf[i];
    }
    // Filled a block, do the SHA256 transform
    sha256_transform(state->r, state->buf, w, r);
    buf += (UInt4)64 - rem;
    len -= (UInt4)64 - rem;

    // Hash full blocks
    while (len >= 64) {
        sha256_transform(state->r, (const UInt1 *)buf, w, r);
        buf += 64;
        len -= 64;
    }

    // Store remainder in buffer
    for (i = 0; i < len; i++) {
        state->buf[i] = buf[i];
    }
    memset(w, 0x0, sizeof(w));
    memset(r, 0x0, sizeof(r));

    return 0;
}

static int sha256_final(sha256_state_t * state)
{
    UInt8 rem;
    UInt8 i;
    UInt4 w[64];
    UInt4 r[8];

    rem = (state->count >> 3) & 0x3f;
    state->buf[rem] = 0x80;
    if (rem < 56) {
        for (i = 1; i < 56 - rem; i++) {
            state->buf[rem + i] = 0x00;
        }
    }
    else {
        for (i = 1; i < (UInt4)64 - rem; i++) {
            state->buf[rem + i] = 0x00;
        }
        sha256_transform(state->r, state->buf, w, r);
        memset(state->buf, 0, 56);
    }
    store64be((UInt8 *)(&state->buf[56]), state->count);

    sha256_transform(state->r, state->buf, w, r);

    return 0;
}

Obj FuncGAP_SHA256_INIT(Obj self)
{
    Obj              result;
    sha256_state_t * sptr;

    result = NewBag(T_DATOBJ, sizeof(UInt4) + sizeof(sha256_state_t));
    SET_TYPE_OBJ(result, GAP_SHA256_State_Type);

    sptr = (sha256_state_t *)(&ADDR_OBJ(result)[1]);
    sha256_init(sptr);

    return result;
}

Obj FuncGAP_SHA256_UPDATE(Obj self, Obj state, Obj bytes)
{
    sha256_state_t * sptr;

    RequireArgumentCondition(SELF_NAME, state,
                             IS_DATOBJ(state) &&
                                 TYPE_OBJ(state) == GAP_SHA256_State_Type,
                             "must be a SHA256 state");
    RequireStringRep(SELF_NAME, bytes);

    sptr = (sha256_state_t *)(&ADDR_OBJ(state)[1]);
    sha256_update(sptr, CHARS_STRING(bytes), GET_LEN_STRING(bytes));
    CHANGED_BAG(state);

    return 0;
}

Obj FuncGAP_SHA256_FINAL(Obj self, Obj state)
{
    Obj              result;
    sha256_state_t * sptr;
    int              i;

    RequireArgumentCondition(SELF_NAME, state,
                             IS_DATOBJ(state) &&
                                 TYPE_OBJ(state) == GAP_SHA256_State_Type,
                             "must be a SHA256 state");

    result = NEW_PLIST(T_PLIST, 8);
    SET_LEN_PLIST(result, 8);

    sptr = (sha256_state_t *)(&ADDR_OBJ(state)[1]);
    sha256_final(sptr);
    CHANGED_BAG(state);

    for (i = 0; i < 8; i++) {
        SET_ELM_PLIST(result, i + 1, ObjInt_UInt(sptr->r[i]));
        CHANGED_BAG(result);
    }
    return result;
}

Obj FuncGAP_SHA256_HMAC(Obj self, Obj key, Obj text)
{
    UInt           i, klen;
    UInt1          k_ipad[64], k_opad[64];
    UInt1          digest[32];
    sha256_state_t st;
    Obj            result;

    RequireStringRep(SELF_NAME, key);
    RequireStringRep(SELF_NAME, text);

    memset(k_ipad, 0x36, sizeof(k_ipad));
    memset(k_opad, 0x5c, sizeof(k_opad));

    klen = GET_LEN_STRING(key);
    if (GET_LEN_STRING(key) > 64) {
        sha256_init(&st);
        sha256_update(&st, CHARS_STRING(key), klen);
        sha256_final(&st);

        be32encode(digest, st.r, sizeof(digest));
        klen = 32;

        for (i = 0; i < klen; i++) {
            k_ipad[i] ^= digest[i];
            k_opad[i] ^= digest[i];
        }
    }
    else {
        for (i = 0; i < klen; i++) {
            k_ipad[i] ^= CHARS_STRING(key)[i];
            k_opad[i] ^= CHARS_STRING(key)[i];
        }
    }

    sha256_init(&st);
    sha256_update(&st, k_ipad, 64);
    sha256_update(&st, CHARS_STRING(text), GET_LEN_STRING(text));
    sha256_final(&st);

    be32encode(digest, st.r, sizeof(digest));
    sha256_init(&st);
    sha256_update(&st, k_opad, 64);
    sha256_update(&st, digest, 32);
    sha256_final(&st);

    result = NEW_PLIST(T_PLIST, 8);
    SET_LEN_PLIST(result, 8);
    for (i = 0; i < 8; i++) {
        SET_ELM_PLIST(result, i + 1, ObjInt_UInt(st.r[i]));
        CHANGED_BAG(result);
    }
    return result;
}

// Table of functions to export
static StructGVarFunc GVarFuncs[] = {
    GVAR_FUNC_0ARGS(GAP_SHA256_INIT),
    GVAR_FUNC_2ARGS(GAP_SHA256_UPDATE, state, bytes),
    GVAR_FUNC_1ARGS(GAP_SHA256_FINAL, state),
    GVAR_FUNC_2ARGS(GAP_SHA256_HMAC, key, text),

    { 0 }    // Finish with an empty entry
};

/****************************************************************************
**
*F  InitKernel( <module> ) . . . . . . .  initialise kernel data structures
*/

static Int InitKernel(StructInitInfo * module)
{
    ImportGVarFromLibrary("GAP_SHA256_State_Type", &GAP_SHA256_State_Type);

    // init filters and functions
    InitHdlrFuncsFromTable(GVarFuncs);

    // return success
    return 0;
}

/****************************************************************************
**
*F  InitLibrary( <module> ) . . . . . . .  initialise library data structures
*/

static Int InitLibrary(StructInitInfo * module)
{
    // init filters and functions
    InitGVarFuncsFromTable(GVarFuncs);

    return 0;
}

/****************************************************************************
**
*F  InitSHA256() . . . . . . . . . . . . . . . . . .  table of init functions
*/

static StructInitInfo module = {
    // init struct using C99 designated initializers; for a full list of
    // fields, please refer to the definition of StructInitInfo
    .type = MODULE_BUILTIN,
    .name = "crypting",
    .initKernel = InitKernel,
    .initLibrary = InitLibrary,
};

StructInitInfo * InitSHA256(void)
{
    return &module;
}

69%


¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.