1. Вы находитесь в архивной версии форума xaker.name. Здесь собраны темы с 2007 по 2012 год, большинство инструкций и мануалов уже неактуальны.
    Скрыть объявление

MD5, SHA1, SHA224, SHA256, SHA384 or SHA512

Тема в разделе "C/C++", создана пользователем Robo, 11 дек 2007.

  1. Robo

    Robo ░░▒▓█▓▒░░ Модератор

    Регистрация:
    10 авг 2007
    Сообщения:
    301
    Симпатии:
    169
    Баллы:
    0
    Код:
    /* Compute MD5, SHA1, SHA224, SHA256, SHA384 or SHA512 checksum of files or strings
       Copyright (C) 1995-2007 Free Software Foundation, Inc.
    
       This program is free software: you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation, either version 3 of the License, or
       (at your option) any later version.
    
       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.
    
       You should have received a copy of the GNU General Public License
       along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
    
    /* Written by Ulrich Drepper <[email protected]>.  */
    
    #include <config.h>
    
    #include <getopt.h>
    #include <sys/types.h>
    
    #include "system.h"
    
    #if HASH_ALGO_MD5
    # include "md5.h"
    #endif
    #if HASH_ALGO_SHA1
    # include "sha1.h"
    #endif
    #if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
    # include "sha256.h"
    #endif
    #if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
    # include "sha512.h"
    #endif
    #include "error.h"
    #include "stdio--.h"
    
    /* The official name of this program (e.g., no `g' prefix).  */
    #if HASH_ALGO_MD5
    # define PROGRAM_NAME "md5sum"
    # define DIGEST_TYPE_STRING "MD5"
    # define DIGEST_STREAM md5_stream
    # define DIGEST_BITS 128
    # define DIGEST_REFERENCE "RFC 1321"
    # define DIGEST_ALIGN 4
    #elif HASH_ALGO_SHA1
    # define PROGRAM_NAME "sha1sum"
    # define DIGEST_TYPE_STRING "SHA1"
    # define DIGEST_STREAM sha1_stream
    # define DIGEST_BITS 160
    # define DIGEST_REFERENCE "FIPS-180-1"
    # define DIGEST_ALIGN 4
    #elif HASH_ALGO_SHA256
    # define PROGRAM_NAME "sha256sum"
    # define DIGEST_TYPE_STRING "SHA256"
    # define DIGEST_STREAM sha256_stream
    # define DIGEST_BITS 256
    # define DIGEST_REFERENCE "FIPS-180-2"
    # define DIGEST_ALIGN 4
    #elif HASH_ALGO_SHA224
    # define PROGRAM_NAME "sha224sum"
    # define DIGEST_TYPE_STRING "SHA224"
    # define DIGEST_STREAM sha224_stream
    # define DIGEST_BITS 224
    # define DIGEST_REFERENCE "RFC 3874"
    # define DIGEST_ALIGN 4
    #elif HASH_ALGO_SHA512
    # define PROGRAM_NAME "sha512sum"
    # define DIGEST_TYPE_STRING "SHA512"
    # define DIGEST_STREAM sha512_stream
    # define DIGEST_BITS 512
    # define DIGEST_REFERENCE "FIPS-180-2"
    # define DIGEST_ALIGN 8
    #elif HASH_ALGO_SHA384
    # define PROGRAM_NAME "sha384sum"
    # define DIGEST_TYPE_STRING "SHA384"
    # define DIGEST_STREAM sha384_stream
    # define DIGEST_BITS 384
    # define DIGEST_REFERENCE "FIPS-180-2"
    # define DIGEST_ALIGN 8
    #else
    # error "Can't decide which hash algorithm to compile."
    #endif
    
    #define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
    #define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
    
    #define AUTHORS "Ulrich Drepper", "Scott Miller", "David Madore"
    
    /* The minimum length of a valid digest line.  This length does
       not include any newline character at the end of a line.  */
    #define MIN_DIGEST_LINE_LENGTH \
      (DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
       + 2 /* blank and binary indicator */ \
       + 1 /* minimum filename length */ )
    
    /* True if any of the files read were the standard input. */
    static bool have_read_stdin;
    
    /* The minimum length of a valid checksum line for the selected algorithm.  */
    static size_t min_digest_line_length;
    
    /* Set to the length of a digest hex string for the selected algorithm.  */
    static size_t digest_hex_bytes;
    
    /* With --check, don't generate any output.
       The exit code indicates success or failure.  */
    static bool status_only = false;
    
    /* With --check, print a message to standard error warning about each
       improperly formatted checksum line.  */
    static bool warn = false;
    
    /* The name this program was run with.  */
    char *program_name;
    
    /* For long options that have no equivalent short option, use a
       non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
    enum
    {
      STATUS_OPTION = CHAR_MAX + 1
    };
    
    static const struct option long_options[] =
    {
      { "binary", no_argument, NULL, 'b' },
      { "check", no_argument, NULL, 'c' },
      { "status", no_argument, NULL, STATUS_OPTION },
      { "text", no_argument, NULL, 't' },
      { "warn", no_argument, NULL, 'w' },
      { GETOPT_HELP_OPTION_DECL },
      { GETOPT_VERSION_OPTION_DECL },
      { NULL, 0, NULL, 0 }
    };
    
    void
    usage (int status)
    {
      if (status != EXIT_SUCCESS)
        fprintf (stderr, _("Try `%s --help' for more information.\n"),
    	     program_name);
      else
        {
          printf (_("\
    Usage: %s [OPTION] [FILE]...\n\
    Print or check %s (%d-bit) checksums.\n\
    With no FILE, or when FILE is -, read standard input.\n\
    \n\
    "),
    	      program_name,
    	      DIGEST_TYPE_STRING,
    	      DIGEST_BITS);
          if (O_BINARY)
    	fputs (_("\
      -b, --binary            read in binary mode (default unless reading tty stdin)\n\
    "), stdout);
          else
    	fputs (_("\
      -b, --binary            read in binary mode\n\
    "), stdout);
          printf (_("\
      -c, --check             read %s sums from the FILEs and check them\n"),
    	      DIGEST_TYPE_STRING);
          if (O_BINARY)
    	fputs (_("\
      -t, --text              read in text mode (default if reading tty stdin)\n\
    "), stdout);
          else
    	fputs (_("\
      -t, --text              read in text mode (default)\n\
    "), stdout);
          fputs (_("\
    \n\
    The following two options are useful only when verifying checksums:\n\
          --status            don't output anything, status code shows success\n\
      -w, --warn              warn about improperly formatted checksum lines\n\
    \n\
    "), stdout);
          fputs (HELP_OPTION_DESCRIPTION, stdout);
          fputs (VERSION_OPTION_DESCRIPTION, stdout);
          printf (_("\
    \n\
    The sums are computed as described in %s.  When checking, the input\n\
    should be a former output of this program.  The default mode is to print\n\
    a line with checksum, a character indicating type (`*' for binary, ` ' for\n\
    text), and name for each FILE.\n"),
    	      DIGEST_REFERENCE);
          emit_bug_reporting_address ();
        }
    
      exit (status);
    }
    
    #define ISWHITE(c) ((c) == ' ' || (c) == '\t')
    
    /* Split the checksum string S (of length S_LEN) from a BSD 'md5' or
       'sha1' command into two parts: a hexadecimal digest, and the file
       name.  S is modified.  Return true if successful.  */
    
    static bool
    bsd_split_3 (char *s, size_t s_len, unsigned char **hex_digest, char **file_name)
    {
      size_t i;
    
      *file_name = s;
    
      /* Find end of filename. The BSD 'md5' and 'sha1' commands do not escape
         filenames, so search backwards for the last ')'. */
      i = s_len - 1;
      while (i && s[i] != ')')
        i--;
    
      if (s[i] != ')')
        return false;
    
      s[i++] = '\0';
    
      while (ISWHITE (s[i]))
        i++;
    
      if (s[i] != '=')
        return false;
    
      i++;
    
      while (ISWHITE (s[i]))
        i++;
    
      *hex_digest = (unsigned char *) &s[i];
      return true;
    }
    
    /* Split the string S (of length S_LEN) into three parts:
       a hexadecimal digest, binary flag, and the file name.
       S is modified.  Return true if successful.  */
    
    static bool
    split_3 (char *s, size_t s_len,
    	 unsigned char **hex_digest, int *binary, char **file_name)
    {
      size_t i;
      bool escaped_filename = false;
      size_t algo_name_len;
    
      i = 0;
      while (ISWHITE (s[i]))
        ++i;
    
      /* Check for BSD-style checksum line. */
      algo_name_len = strlen (DIGEST_TYPE_STRING);
      if (strncmp (s + i, DIGEST_TYPE_STRING, algo_name_len) == 0)
        {
          if (strncmp (s + i + algo_name_len, " (", 2) == 0)
    	{
    	  *binary = 0;
    	  return bsd_split_3 (s +      i + algo_name_len + 2,
    			      s_len - (i + algo_name_len + 2),
    			      hex_digest, file_name);
    	}
        }
    
      /* Ignore this line if it is too short.
         Each line must have at least `min_digest_line_length - 1' (or one more, if
         the first is a backslash) more characters to contain correct message digest
         information.  */
      if (s_len - i < min_digest_line_length + (s[i] == '\\'))
        return false;
    
      if (s[i] == '\\')
        {
          ++i;
          escaped_filename = true;
        }
      *hex_digest = (unsigned char *) &s[i];
    
      /* The first field has to be the n-character hexadecimal
         representation of the message digest.  If it is not followed
         immediately by a white space it's an error.  */
      i += digest_hex_bytes;
      if (!ISWHITE (s[i]))
        return false;
    
      s[i++] = '\0';
    
      if (s[i] != ' ' && s[i] != '*')
        return false;
      *binary = (s[i++] == '*');
    
      /* All characters between the type indicator and end of line are
         significant -- that includes leading and trailing white space.  */
      *file_name = &s[i];
    
      if (escaped_filename)
        {
          /* Translate each `\n' string in the file name to a NEWLINE,
    	 and each `\\' string to a backslash.  */
    
          char *dst = &s[i];
    
          while (i < s_len)
    	{
    	  switch (s[i])
    	    {
    	    case '\\':
    	      if (i == s_len - 1)
    		{
    		  /* A valid line does not end with a backslash.  */
    		  return false;
    		}
    	      ++i;
    	      switch (s[i++])
    		{
    		case 'n':
    		  *dst++ = '\n';
    		  break;
    		case '\\':
    		  *dst++ = '\\';
    		  break;
    		default:
    		  /* Only `\' or `n' may follow a backslash.  */
    		  return false;
    		}
    	      break;
    
    	    case '\0':
    	      /* The file name may not contain a NUL.  */
    	      return false;
    	      break;
    
    	    default:
    	      *dst++ = s[i++];
    	      break;
    	    }
    	}
          *dst = '\0';
        }
      return true;
    }
    
    static bool
    hex_digits (unsigned char const *s)
    {
      while (*s)
        {
          if (!isxdigit (*s))
            return false;
          ++s;
        }
      return true;
    }
    
    /* An interface to the function, DIGEST_STREAM.
       Operate on FILENAME (it may be "-").
    
       *BINARY indicates whether the file is binary.  BINARY < 0 means it
       depends on whether binary mode makes any difference and the file is
       a terminal; in that case, clear *BINARY if the file was treated as
       text because it was a terminal.
    
       Put the checksum in *BIN_RESULT, which must be properly aligned.
       Return true if successful.  */
    
    static bool
    digest_file (const char *filename, int *binary, unsigned char *bin_result)
    {
      FILE *fp;
      int err;
      bool is_stdin = STREQ (filename, "-");
    
      if (is_stdin)
        {
          have_read_stdin = true;
          fp = stdin;
          if (O_BINARY && *binary)
    	{
    	  if (*binary < 0)
    	    *binary = ! isatty (STDIN_FILENO);
    	  if (*binary)
    	    freopen (NULL, "rb", stdin);
    	}
        }
      else
        {
          fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
          if (fp == NULL)
    	{
    	  error (0, errno, "%s", filename);
    	  return false;
    	}
        }
    
      err = DIGEST_STREAM (fp, bin_result);
      if (err)
        {
          error (0, errno, "%s", filename);
          if (fp != stdin)
    	fclose (fp);
          return false;
        }
    
      if (!is_stdin && fclose (fp) != 0)
        {
          error (0, errno, "%s", filename);
          return false;
        }
    
      return true;
    }
    
    static bool
    digest_check (const char *checkfile_name)
    {
      FILE *checkfile_stream;
      uintmax_t n_properly_formatted_lines = 0;
      uintmax_t n_mismatched_checksums = 0;
      uintmax_t n_open_or_read_failures = 0;
      unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
      /* Make sure bin_buffer is properly aligned. */
      unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
      uintmax_t line_number;
      char *line;
      size_t line_chars_allocated;
      bool is_stdin = STREQ (checkfile_name, "-");
    
      if (is_stdin)
        {
          have_read_stdin = true;
          checkfile_name = _("standard input");
          checkfile_stream = stdin;
        }
      else
        {
          checkfile_stream = fopen (checkfile_name, "r");
          if (checkfile_stream == NULL)
    	{
    	  error (0, errno, "%s", checkfile_name);
    	  return false;
    	}
        }
    
      line_number = 0;
      line = NULL;
      line_chars_allocated = 0;
      do
        {
          char *filename;
          int binary;
          unsigned char *hex_digest IF_LINT (= NULL);
          ssize_t line_length;
    
          ++line_number;
          if (line_number == 0)
    	error (EXIT_FAILURE, 0, _("%s: too many checksum lines"),
    	       checkfile_name);
    
          line_length = getline (&line, &line_chars_allocated, checkfile_stream);
          if (line_length <= 0)
    	break;
    
          /* Ignore comment lines, which begin with a '#' character.  */
          if (line[0] == '#')
    	continue;
    
          /* Remove any trailing newline.  */
          if (line[line_length - 1] == '\n')
    	line[--line_length] = '\0';
    
          if (! (split_3 (line, line_length, &hex_digest, &binary, &filename)
    	     && ! (is_stdin && STREQ (filename, "-"))
    	     && hex_digits (hex_digest)))
    	{
    	  if (warn)
    	    {
    	      error (0, 0,
    		     _("%s: %" PRIuMAX
    		       ": improperly formatted %s checksum line"),
    		     checkfile_name, line_number,
    		     DIGEST_TYPE_STRING);
    	    }
    	}
          else
    	{
    	  static const char bin2hex[] = { '0', '1', '2', '3',
    					  '4', '5', '6', '7',
    					  '8', '9', 'a', 'b',
    					  'c', 'd', 'e', 'f' };
    	  bool ok;
    
    	  ++n_properly_formatted_lines;
    
    	  ok = digest_file (filename, &binary, bin_buffer);
    
    	  if (!ok)
    	    {
    	      ++n_open_or_read_failures;
    	      if (!status_only)
    		{
    		  printf (_("%s: FAILED open or read\n"), filename);
    		  fflush (stdout);
    		}
    	    }
    	  else
    	    {
    	      size_t digest_bin_bytes = digest_hex_bytes / 2;
    	      size_t cnt;
    	      /* Compare generated binary number with text representation
    		 in check file.  Ignore case of hex digits.  */
    	      for (cnt = 0; cnt < digest_bin_bytes; ++cnt)
    		{
    		  if (tolower (hex_digest[2 * cnt])
    		      != bin2hex[bin_buffer[cnt] >> 4]
    		      || (tolower (hex_digest[2 * cnt + 1])
    			  != (bin2hex[bin_buffer[cnt] & 0xf])))
    		    break;
    		}
    	      if (cnt != digest_bin_bytes)
    		++n_mismatched_checksums;
    
    	      if (!status_only)
    		{
    		  printf ("%s: %s\n", filename,
    			  (cnt != digest_bin_bytes ? _("FAILED") : _("OK")));
    		  fflush (stdout);
    		}
    	    }
    	}
        }
      while (!feof (checkfile_stream) && !ferror (checkfile_stream));
    
      free (line);
    
      if (ferror (checkfile_stream))
        {
          error (0, 0, _("%s: read error"), checkfile_name);
          return false;
        }
    
      if (!is_stdin && fclose (checkfile_stream) != 0)
        {
          error (0, errno, "%s", checkfile_name);
          return false;
        }
    
      if (n_properly_formatted_lines == 0)
        {
          /* Warn if no tests are found.  */
          error (0, 0, _("%s: no properly formatted %s checksum lines found"),
    	     checkfile_name, DIGEST_TYPE_STRING);
        }
      else
        {
          if (!status_only)
    	{
    	  if (n_open_or_read_failures != 0)
    	    error (0, 0,
    		   ngettext ("WARNING: %" PRIuMAX " of %" PRIuMAX
    			     " listed file could not be read",
    			     "WARNING: %" PRIuMAX " of %" PRIuMAX
    			     " listed files could not be read",
    			     select_plural (n_properly_formatted_lines)),
    		   n_open_or_read_failures, n_properly_formatted_lines);
    
    	  if (n_mismatched_checksums != 0)
    	    {
    	      uintmax_t n_computed_checksums =
    		(n_properly_formatted_lines - n_open_or_read_failures);
    	      error (0, 0,
    		     ngettext ("WARNING: %" PRIuMAX " of %" PRIuMAX
    			       " computed checksum did NOT match",
    			       "WARNING: %" PRIuMAX " of %" PRIuMAX
    			       " computed checksums did NOT match",
    			       select_plural (n_computed_checksums)),
    		     n_mismatched_checksums, n_computed_checksums);
    	    }
    	}
        }
    
      return (n_properly_formatted_lines != 0
    	  && n_mismatched_checksums == 0
    	  && n_open_or_read_failures == 0);
    }
    
    int
    main (int argc, char **argv)
    {
      unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + DIGEST_ALIGN];
      /* Make sure bin_buffer is properly aligned. */
      unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, DIGEST_ALIGN);
      bool do_check = false;
      int opt;
      bool ok = true;
      int binary = -1;
    
      /* Setting values of global variables.  */
      initialize_main (&argc, &argv);
      program_name = argv[0];
      setlocale (LC_ALL, "");
      bindtextdomain (PACKAGE, LOCALEDIR);
      textdomain (PACKAGE);
    
      atexit (close_stdout);
    
      while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
        switch (opt)
          {
          case 'b':
    	binary = 1;
    	break;
          case 'c':
    	do_check = true;
    	break;
          case STATUS_OPTION:
    	status_only = true;
    	warn = false;
    	break;
          case 't':
    	binary = 0;
    	break;
          case 'w':
    	status_only = false;
    	warn = true;
    	break;
          case_GETOPT_HELP_CHAR;
          case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
          default:
    	usage (EXIT_FAILURE);
          }
    
      min_digest_line_length = MIN_DIGEST_LINE_LENGTH;
      digest_hex_bytes = DIGEST_HEX_BYTES;
    
      if (0 <= binary && do_check)
        {
          error (0, 0, _("the --binary and --text options are meaningless when "
    		     "verifying checksums"));
          usage (EXIT_FAILURE);
        }
    
      if (status_only & !do_check)
        {
          error (0, 0,
           _("the --status option is meaningful only when verifying checksums"));
          usage (EXIT_FAILURE);
        }
    
      if (warn & !do_check)
        {
          error (0, 0,
           _("the --warn option is meaningful only when verifying checksums"));
          usage (EXIT_FAILURE);
        }
    
      if (!O_BINARY && binary < 0)
        binary = 0;
    
      if (optind == argc)
        argv[argc++] = "-";
    
      for (; optind < argc; ++optind)
        {
          char *file = argv[optind];
    
          if (do_check)
    	ok &= digest_check (file);
          else
    	{
    	  int file_is_binary = binary;
    
    	  if (! digest_file (file, &file_is_binary, bin_buffer))
    	    ok = false;
    	  else
    	    {
    	      size_t i;
    
    	      /* Output a leading backslash if the file name contains
    		 a newline or backslash.  */
    	      if (strchr (file, '\n') || strchr (file, '\\'))
    		putchar ('\\');
    
    	      for (i = 0; i < (digest_hex_bytes / 2); ++i)
    		printf ("%02x", bin_buffer[i]);
    
    	      putchar (' ');
    	      if (file_is_binary)
    		putchar ('*');
    	      else
    		putchar (' ');
    
    	      /* Translate each NEWLINE byte to the string, "\\n",
    		 and each backslash to "\\\\".  */
    	      for (i = 0; i < strlen (file); ++i)
    		{
    		  switch (file[i])
    		    {
    		    case '\n':
    		      fputs ("\\n", stdout);
    		      break;
    
    		    case '\\':
    		      fputs ("\\\\", stdout);
    		      break;
    
    		    default:
    		      putchar (file[i]);
    		      break;
    		    }
    		}
    	      putchar ('\n');
    	    }
    	}
        }
    
      if (have_read_stdin && fclose (stdin) == EOF)
        error (EXIT_FAILURE, errno, _("standard input"));
    
      exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
    }
    
    Добавлено через 32 минуты
    эмм... а причём тут это? Просто мощьный алго! А если нет md5.h - качай
    ну или вот:

    MD5.H
    Код:
    #ifndef  _MD5_H
    #define  _MD5_H
    
    namespace  md5
    {
      #ifndef  uint8
      #define uint8   unsigned char
      #endif
    
      #ifndef  uint32
      #define uint32  unsigned long int
      #endif
    
      typedef struct
       {
        uint32 total[ 2 ];
        uint32 state[ 4 ];
        uint8 buffer[ 64 ];
      }
      md5_context;
    
      void  md5_starts( md5_context *ctx );
      void  md5_update( md5_context *ctx, uint8 *input, uint32 length );
      void md5_finish( md5_context *ctx, uint8 digest[16 ] );
    }
    
    #endif  /* md5.h */
    
    MD5.CPP
    Код:
    /*
     *  RFC 1321 compliant MD5 implementation
     *
     */
    
    #include  "md5.h"
    #include  <string>
    
    #pragma warning( disable : 4005  )
    
    using namespace  std;
    
    namespace  md5
    {
    
        #define  GET_UINT32(n,b,i)                       \
        {                                               \
            (n) = ( (uint32) (b)[(i)    ]       )       \
                | ( (uint32) (b)[(i) + 1] <<  8  )       \
                | ( (uint32) (b)[(i) + 2] << 16  )       \
                | ( (uint32) (b)[(i) + 3] << 24  );      \
        }
    
        #define  PUT_UINT32(n,b,i)                       \
        {                                               \
            (b)[(i)    ] = (uint8) ( (n)       );       \
            (b)[(i) + 1] = (uint8) ( (n) >>  8  );       \
            (b)[(i) + 2] = (uint8) ( (n) >> 16  );       \
            (b)[(i) + 3] = (uint8) ( (n) >> 24  );       \
        }
    
        void  md5_starts( md5_context *ctx )
        {
            ctx->total[ 0] = 0 ;
            ctx->total[ 1] = 0 ;
    
            ctx->state[ 0] = 0x67452301 ;
            ctx->state[ 1] = 0xEFCDAB89 ;
            ctx->state[ 2] = 0x98BADCFE ;
            ctx->state[ 3] = 0x10325476 ;
        }
    
        void md5_process( md5_context *ctx, uint8 data[64 ] )
        {
            uint32 X[ 16 ], A, B, C, D;
    
            GET_UINT32( X[ 0],  data,  0  );
            GET_UINT32( X[ 1],  data,  4  );
            GET_UINT32( X[ 2],  data,  8  );
            GET_UINT32( X[ 3],  data, 12  );
            GET_UINT32( X[ 4],  data, 16  );
            GET_UINT32( X[ 5],  data, 20  );
            GET_UINT32( X[ 6],  data, 24  );
            GET_UINT32( X[ 7],  data, 28  );
            GET_UINT32( X[ 8],  data, 32  );
            GET_UINT32( X[ 9],  data, 36  );
            GET_UINT32( X[ 10], data, 40  );
            GET_UINT32( X[ 11], data, 44  );
            GET_UINT32( X[ 12], data, 48  );
            GET_UINT32( X[ 13], data, 52  );
            GET_UINT32( X[ 14], data, 56  );
            GET_UINT32( X[ 15], data, 60  );
    
        #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32  - n)))
    
        #define  P(a,b,c,d,k,s,t)                                \
        {                                                       \
            a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
        }
    
            A = ctx->state[ 0 ];
            B = ctx->state[ 1 ];
            C = ctx->state[ 2 ];
            D = ctx->state[ 3 ];
    
        #define  F(x,y,z) (z ^ (x & (y ^ z)))
    
            P( A, B, C, D,  0,  7, 0xD76AA478  );
            P( D, A, B, C,  1, 12, 0xE8C7B756  );
            P( C, D, A, B,  2, 17, 0x242070DB  );
            P( B, C, D, A,  3, 22, 0xC1BDCEEE  );
            P( A, B, C, D,  4,  7, 0xF57C0FAF  );
            P( D, A, B, C,  5, 12, 0x4787C62A  );
            P( C, D, A, B,  6, 17, 0xA8304613  );
            P( B, C, D, A,  7, 22, 0xFD469501  );
            P( A, B, C, D,  8,  7, 0x698098D8  );
            P( D, A, B, C,  9, 12, 0x8B44F7AF  );
            P( C, D, A, B, 10, 17, 0xFFFF5BB1  );
            P( B, C, D, A, 11, 22, 0x895CD7BE  );
            P( A, B, C, D, 12,  7, 0x6B901122  );
            P( D, A, B, C, 13, 12, 0xFD987193  );
            P( C, D, A, B, 14, 17, 0xA679438E  );
            P( B, C, D, A, 15, 22, 0x49B40821  );
    
        #undef  F
    
        #define  F(x,y,z) (y ^ (z & (x ^ y)))
    
            P( A, B, C, D,  1,  5, 0xF61E2562  );
            P( D, A, B, C,  6,  9, 0xC040B340  );
            P( C, D, A, B, 11, 14, 0x265E5A51  );
            P( B, C, D, A,  0, 20, 0xE9B6C7AA  );
            P( A, B, C, D,  5,  5, 0xD62F105D  );
            P( D, A, B, C, 10,  9, 0x02441453  );
            P( C, D, A, B, 15, 14, 0xD8A1E681  );
            P( B, C, D, A,  4, 20, 0xE7D3FBC8  );
            P( A, B, C, D,  9,  5, 0x21E1CDE6  );
            P( D, A, B, C, 14,  9, 0xC33707D6  );
            P( C, D, A, B,  3, 14, 0xF4D50D87  );
            P( B, C, D, A,  8, 20, 0x455A14ED  );
            P( A, B, C, D, 13,  5, 0xA9E3E905  );
            P( D, A, B, C,  2,  9, 0xFCEFA3F8  );
            P( C, D, A, B,  7, 14, 0x676F02D9  );
            P( B, C, D, A, 12, 20, 0x8D2A4C8A  );
    
        #undef  F
        
        #define  F(x,y,z) (x ^ y ^ z)
    
            P( A, B, C, D,  5,  4, 0xFFFA3942  );
            P( D, A, B, C,  8, 11, 0x8771F681  );
            P( C, D, A, B, 11, 16, 0x6D9D6122  );
            P( B, C, D, A, 14, 23, 0xFDE5380C  );
            P( A, B, C, D,  1,  4, 0xA4BEEA44  );
            P( D, A, B, C,  4, 11, 0x4BDECFA9  );
            P( C, D, A, B,  7, 16, 0xF6BB4B60  );
            P( B, C, D, A, 10, 23, 0xBEBFBC70  );
            P( A, B, C, D, 13,  4, 0x289B7EC6  );
            P( D, A, B, C,  0, 11, 0xEAA127FA  );
            P( C, D, A, B,  3, 16, 0xD4EF3085  );
            P( B, C, D, A,  6, 23, 0x04881D05  );
            P( A, B, C, D,  9,  4, 0xD9D4D039  );
            P( D, A, B, C, 12, 11, 0xE6DB99E5  );
            P( C, D, A, B, 15, 16, 0x1FA27CF8  );
            P( B, C, D, A,  2, 23, 0xC4AC5665  );
    
        #undef  F
    
        #define  F(x,y,z) (y ^ (x | ~z))
    
            P( A, B, C, D,  0,  6, 0xF4292244  );
            P( D, A, B, C,  7, 10, 0x432AFF97  );
            P( C, D, A, B, 14, 15, 0xAB9423A7  );
            P( B, C, D, A,  5, 21, 0xFC93A039  );
            P( A, B, C, D, 12,  6, 0x655B59C3  );
            P( D, A, B, C,  3, 10, 0x8F0CCC92  );
            P( C, D, A, B, 10, 15, 0xFFEFF47D  );
            P( B, C, D, A,  1, 21, 0x85845DD1  );
            P( A, B, C, D,  8,  6, 0x6FA87E4F  );
            P( D, A, B, C, 15, 10, 0xFE2CE6E0  );
            P( C, D, A, B,  6, 15, 0xA3014314  );
            P( B, C, D, A, 13, 21, 0x4E0811A1  );
            P( A, B, C, D,  4,  6, 0xF7537E82  );
            P( D, A, B, C, 11, 10, 0xBD3AF235  );
            P( C, D, A, B,  2, 15, 0x2AD7D2BB  );
            P( B, C, D, A,  9, 21, 0xEB86D391  );
    
        #undef  F
    
            ctx->state[ 0 ] += A;
            ctx->state[ 1 ] += B;
            ctx->state[ 2 ] += C;
            ctx->state[ 3 ] += D;
        }
    
        void  md5_update( md5_context *ctx, uint8 *input, uint32 length )
        {
            uint32 left, fill;
    
            if( ! length ) return ;
    
            left = ctx->total[ 0] & 0x3F ;
            fill = 64  - left;
    
            ctx->total[ 0 ] += length;
            ctx->total[ 0] &= 0xFFFFFFFF ;
    
            if( ctx->total[0 ] < length )
                ctx->total[ 1 ]++;
    
            if ( left && length >= fill )
            {
                memcpy( ( void  *) (ctx->buffer + left),
                        ( void  *) input, fill );
                md5_process( ctx, ctx->buffer );
                length -= fill;
                input  += fill;
                left = 0 ;
            }
    
            while( length >= 64  )
            {
                md5_process( ctx, input );
                length -= 64 ;
                input  += 64 ;
            }
    
            if ( length )
            {
                memcpy( ( void  *) (ctx->buffer + left),
                        ( void  *) input, length );
            }
        }
    
        static uint8 md5_padding[64 ] =
        {
         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0
         };
    
        void md5_finish( md5_context *ctx, uint8 digest[16 ] )
        {
            uint32 last, padn;
            uint32 high, low;
            uint8 msglen[ 8 ];
    
            high = ( ctx->total[ 0] >> 29  )
                 | ( ctx->total[ 1] <<  3  );
            low  = ( ctx->total[ 0] <<  3  );
    
            PUT_UINT32( low,  msglen, 0  );
            PUT_UINT32( high, msglen, 4  );
    
            last = ctx->total[ 0] & 0x3F ;
            padn = ( last < 56 ) ? ( 56 - last ) : ( 120  - last );
    
            md5_update( ctx, md5_padding, padn );
            md5_update( ctx, msglen, 8  );
    
            PUT_UINT32( ctx->state[ 0], digest,  0  );
            PUT_UINT32( ctx->state[ 1], digest,  4  );
            PUT_UINT32( ctx->state[ 2], digest,  8  );
            PUT_UINT32( ctx->state[ 3], digest, 12  );
        }
    }
    
     
    Последнее редактирование: 11 дек 2007

Поделиться этой страницей