Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/Vendor/Scrypt/src/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 8 kB image not shown  

Quelle  sha256.c   Sprache: C

 

#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "sha256.h"
#include "common.h"


/* See: https://tools.ietf.org/html/rfc6234#section-5.1 */
static uint32_t scrypt_sha256_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 uint32_t scrypt_sha256_h[] = {
  0x6a09e667,
  0xbb67ae85,
  0x3c6ef372,
  0xa54ff53a,
  0x510e527f,
  0x9b05688c,
  0x1f83d9ab,
  0x5be0cd19
};


/* CH( x, y, z) = (x AND y) XOR ( (NOT x) AND z) */
static uint32_t scrypt_sha256_ch(uint32_t x, uint32_t y, uint32_t z) {
  return (x & y) ^ ((~x) & z);
}


/* MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) */
static uint32_t scrypt_sha256_maj(uint32_t x, uint32_t y, uint32_t z) {
  return (x & y) ^ (x & z) ^ (y & z);
}


static uint32_t scrypt_sha256_rotr(uint32_t n, int s) {
  return (n << (32 - s)) | (n >> s);
}


/* BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x) */
static uint32_t scrypt_sha256_bsig0(uint32_t x) {
  return scrypt_sha256_rotr(x, 2) ^
         scrypt_sha256_rotr(x, 13) ^
         scrypt_sha256_rotr(x, 22);
}


/* BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x) */
static uint32_t scrypt_sha256_bsig1(uint32_t x) {
  return scrypt_sha256_rotr(x, 6) ^
         scrypt_sha256_rotr(x, 11) ^
         scrypt_sha256_rotr(x, 25);
}


/* SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x) */
static uint32_t scrypt_sha256_ssig0(uint32_t x) {
  return scrypt_sha256_rotr(x, 7) ^
         scrypt_sha256_rotr(x, 18) ^
         (x >> 3);
}


/* SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x) */
static uint32_t scrypt_sha256_ssig1(uint32_t x) {
  return scrypt_sha256_rotr(x, 17) ^
         scrypt_sha256_rotr(x, 19) ^
         (x >> 10);
}


void scrypt_sha256_init(scrypt_sha256_t* sha256) {
  memcpy(sha256->h, scrypt_sha256_h, sizeof(scrypt_sha256_h));
  sha256->length = 0;
}


static void scrypt_sha256_fill_block(const uint8_t* input,
                                     uint32_t* output,
                                     size_t n) {
  size_t i;

  for (i = 0; i < n; i++) {
    output[i] = ((uint32_t) input[i * 4] << 24) |
                ((uint32_t) input[i * 4 + 1] << 16) |
                ((uint32_t) input[i * 4 + 2] << 8) |
                (uint32_t) input[i * 4 + 3];
  }
}


static void scrypt_sha256_process_block(scrypt_sha256_t* sha256,
                                        const uint32_t* block) {
  /*
   *    1. Prepare the message schedule W:
   *         For t = 0 to 15
   *             Wt = M(i)t
   *         For t = 16 to 63
   *             Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(w(t-15)) + W(t-16)
   *
   */

  uint32_t w[64];
  size_t t;
  uint32_t a;
  uint32_t b;
  uint32_t c;
  uint32_t d;
  uint32_t e;
  uint32_t f;
  uint32_t g;
  uint32_t h;

  memcpy(w, block, sizeof(*w) * 16);
  for (t = 16; t < 64; t++) {
    w[t] = scrypt_sha256_ssig1(w[t - 2]) +
           w[t - 7] +
           scrypt_sha256_ssig0(w[t - 15]) +
           w[t - 16];
  }

  /*
   *    2. Initialize the working variables:
   *         a = H(i-1)0
   *         b = H(i-1)1
   *         c = H(i-1)2
   *         d = H(i-1)3
   *         e = H(i-1)4
   *         f = H(i-1)5
   *         g = H(i-1)6
   *         h = H(i-1)7
   */

  a = sha256->h[0];
  b = sha256->h[1];
  c = sha256->h[2];
  d = sha256->h[3];
  e = sha256->h[4];
  f = sha256->h[5];
  g = sha256->h[6];
  h = sha256->h[7];

  /*
   *    3. Perform the main hash computation:
   *       For t = 0 to 63
   *          T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt
   *          T2 = BSIG0(a) + MAJ(a,b,c)
   *          h = g
   *          g = f
   *          f = e
   *          e = d + T1
   *          d = c
   *          c = b
   *          b = a
   *          a = T1 + T2
   */

  for (t = 0; t < 64; t++) {
    uint32_t t1;
    uint32_t t2;

    t1 = h +
         scrypt_sha256_bsig1(e) +
         scrypt_sha256_ch(e, f, g) +
         scrypt_sha256_k[t] +
         w[t];
    t2 = scrypt_sha256_bsig0(a) + scrypt_sha256_maj(a, b, c);
    h = g;
    g = f;
    f = e;
    e = d + t1;
    d = c;
    c = b;
    b = a;
    a = t1 + t2;
  }

  /*
   *    4. Compute the intermediate hash value H(i)
   *       H(i)0 = a + H(i-1)0
   *       H(i)1 = b + H(i-1)1
   *       H(i)2 = c + H(i-1)2
   *       H(i)3 = d + H(i-1)3
   *       H(i)4 = e + H(i-1)4
   *       H(i)5 = f + H(i-1)5
   *       H(i)6 = g + H(i-1)6
   *       H(i)7 = h + H(i-1)7
   */

  sha256->h[0] += a;
  sha256->h[1] += b;
  sha256->h[2] += c;
  sha256->h[3] += d;
  sha256->h[4] += e;
  sha256->h[5] += f;
  sha256->h[6] += g;
  sha256->h[7] += h;
}


void scrypt_sha256_update(scrypt_sha256_t* sha256,
                          const uint8_t* data,
                          size_t size) {
  const uint8_t* p;
  size_t left;

  p = data;
  left = size;

  while (left != 0) {
    size_t off;
    size_t to_copy;
    uint32_t block[16];

    off = sha256->length % kSha256BlockSize;
    to_copy = MIN(left, kSha256BlockSize - off);

    /* Just bufferize to fill the block */
    memcpy(sha256->buffer + off, p, to_copy);
    sha256->length += to_copy;

    p += to_copy;
    left -= to_copy;

    /* Incomplete block - wait for more data */
    if (off + to_copy != kSha256BlockSize)
      break;

    scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block));
    scrypt_sha256_process_block(sha256, block);
  }
}


static void scrypt_sha256_write_uint64_be(uint8_t* data,
                                          uint64_t value,
                                          size_t off) {
  data[off] = value >> 56;
  data[off + 1] = value >> 48;
  data[off + 2] = value >> 40;
  data[off + 3] = value >> 32;
  data[off + 4] = value >> 24;
  data[off + 5] = value >> 16;
  data[off + 6] = value >> 8;
  data[off + 7] = value;
}


void scrypt_sha256_digest(scrypt_sha256_t* sha256, uint8_t* out) {
  /* https://tools.ietf.org/html/rfc6234#section-4.1 */

  /*
   *   Suppose a message has length L < 2^64.  Before it is input to the
   *   hash function, the message is padded on the right as follows:
   *
   *   a. "1" is appended.  Example: if the original message is "01010000",
   *      this is padded to "010100001".
   *
   *   b. K "0"s are appended where K is the smallest, non-negative solution
   *      to the equation
   *
   *         ( L + 1 + K ) mod 512 = 448
   *
   *   c. Then append the 64-bit block that is L in binary representation.
   *      After appending this block, the length of the message will be a
   *      multiple of 512 bits.
   */


  size_t off;
  uint32_t block[16];
  size_t i;
  int has_overflow;

  /* NOTE: It is simple to calculate `k`, but having it is a bit useless, since
   * we know that this algorithm just wants to zero the rest of the block and to
   * put the 64bit length to the end */

  off = (sha256->length % kSha256BlockSize);

  /* (b) */
  memset(sha256->buffer + off, 0, kSha256BlockSize - off);

  /* If padding does not fit in a single block - append 0x80 and zeroes to the
   * current block and flush it.
   * Then fill the block with zeroes and append size to it, and flush it again
   */

  has_overflow = off + 9 > kSha256BlockSize;
  if (has_overflow) {
    /* (a) */
    sha256->buffer[off] |= 0x80;

    scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block));
    scrypt_sha256_process_block(sha256, block);

    off = 0;
    memset(sha256->buffer, 0, kSha256BlockSize);
  }

  /* (c) */
  scrypt_sha256_write_uint64_be(sha256->buffer,
                                sha256->length * 8,
                                kSha256BlockSize - 8);

  /* (a) */
  if (!has_overflow)
    sha256->buffer[off] |= 0x80;

  scrypt_sha256_fill_block(sha256->buffer, block, ARRAY_SIZE(block));
  scrypt_sha256_process_block(sha256, block);

  for (i = 0; i < ARRAY_SIZE(sha256->h); i++) {
    out[i * 4] = sha256->h[i] >> 24;
    out[i * 4 + 1] = sha256->h[i] >> 16;
    out[i * 4 + 2] = sha256->h[i] >> 8;
    out[i * 4 + 3] = sha256->h[i];
  }
}

Messung
CHZG
859510093

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

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 und die Messung sind noch experimentell.