На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Соблюдайте общие правила форума
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Указывайте точные версии Delphi и используемых сетевых библиотек.

Не приветствуется поднятие старых тем. Если ваш вопрос перекликается со старой темой, то для вопроса лучше создать новую тему, а старую указать в первом сообщении с описанием взаимосвязи.

Внимание:
попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Krid, user posted image Rouse_

Модераторы: Krid, Rouse_
  
> Проблема с генератором htpasswd , {отделена by .failer}
    RuSA у меня проблема!!! Делаю программу генератор htpasswd Мне дали исходник программы на турбо паскале.... Там есть MD5 шифрование Моя беда я нипонимаю что с чем шифруется какой ключ и.т.д. MD5 взял из faq тут. Понимаешь мне отчано надо перенести это шифрование логина и пароля на делфи..........

    Вот об этой программе http://www.1gb.ru/default.aspx?ti=6&hti=12

    Нужная мне обработка похоже тут

    ExpandedWrap disabled
        case ALG_APMD5:
              (void) srand((int) time((time_t *) NULL));
              ap_to64(&salt[0], rand(), 8);
              salt[8] = '\0';


    Но я не знаю как её использовать... я не понимаю какие части логина и пароля шифруются.... и какой ключ...



    Вот полный исходник программы... на турбо паскале...

    Посмотри пожалуйста.
    ExpandedWrap disabled
      /* ====================================================================
       * The Apache Software License, Version 1.1
       *
       * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
       * reserved.
       *
       * Redistribution and use in source and binary forms, with or without
       * modification, are permitted provided that the following conditions
       * are met:
       *
       * 1. Redistributions of source code must retain the above copyright
       *    notice, this list of conditions and the following disclaimer.
       *
       * 2. Redistributions in binary form must reproduce the above copyright
       *    notice, this list of conditions and the following disclaimer in
       *    the documentation and/or other materials provided with the
       *    distribution.
       *
       * 3. The end-user documentation included with the redistribution,
       *    if any, must include the following acknowledgment:
       *       "This product includes software developed by the
       *        Apache Software Foundation (http://www.apache.org/)."
       *    Alternately, this acknowledgment may appear in the software itself,
       *    if and wherever such third-party acknowledgments normally appear.
       *
       * 4. The names "Apache" and "Apache Software Foundation" must
       *    not be used to endorse or promote products derived from this
       *    software without prior written permission. For written
       *    permission, please contact apache@apache.org.
       *
       * 5. Products derived from this software may not be called "Apache",
       *    nor may "Apache" appear in their name, without prior written
       *    permission of the Apache Software Foundation.
       *
       * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
       * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
       * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
       * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
       * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
       * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
       * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       * SUCH DAMAGE.
       * ====================================================================
       * ====================================================================
       *
       * This software consists of voluntary contributions made by many
       * individuals on behalf of the Apache Software Foundation.  For more
       * information on the Apache Software Foundation, please see
       * <http://www.apache.org/>.
       *
       * Portions of this software are based upon public domain software
       * originally written at the National Center for Supercomputing Applications,
       * University of Illinois, Urbana-Champaign.
       */
       
      /******************************************************************************
       ******************************************************************************
       * NOTE! This program is not safe as a setuid executable!  Do not make it
       * setuid!
       ******************************************************************************
       *****************************************************************************/
      /*
       * htpasswd.c: simple program for manipulating password file for
       * the Apache HTTP server
       *
       * Originally by Rob McCool
       *
       * Exit values:
       *  0: Success
       *  1: Failure; file access/permission problem
       *  2: Failure; command line syntax problem (usage message issued)
       *  3: Failure; password verification failure
       *  4: Failure; operation interrupted (such as with CTRL/C)
       *  5: Failure; buffer would overflow (username, filename, or computed
       *     record too long)
       *  6: Failure; username contains illegal or reserved characters
       */
       
      #include "ap_config.h"
      #ifndef NETWARE
      #include <sys/types.h>
      #endif
      #include <signal.h>
      #include <errno.h>
      #include "ap.h"
      #include "ap_md5.h"
      #include "ap_sha1.h"
       
      #ifdef HAVE_CRYPT_H
      #include <crypt.h>
      #endif
       
      #ifdef WIN32
      #include <conio.h>
      #include "../os/win32/getopt.h"
      #define unlink _unlink
      #endif
       
      #ifndef CHARSET_EBCDIC
      #define LF 10
      #define CR 13
      #else /*CHARSET_EBCDIC*/
      #define LF '\n'
      #define CR '\r'
      #endif /*CHARSET_EBCDIC*/
       
      #define MAX_STRING_LEN 256
      #define ALG_PLAIN 0
      #define ALG_CRYPT 1
      #define ALG_APMD5 2
      #define ALG_APSHA 3
       
      #define ERR_FILEPERM 1
      #define ERR_SYNTAX 2
      #define ERR_PWMISMATCH 3
      #define ERR_INTERRUPTED 4
      #define ERR_OVERFLOW 5
      #define ERR_BADUSER 6
       
      /*
       * This needs to be declared statically so the signal handler can
       * access it.
       */
      static char *tempfilename;
      /*
       * If our platform knows about the tmpnam() external buffer size, create
       * a buffer to pass in.  This is needed in a threaded environment, or
       * one that thinks it is (like HP-UX).
       */
      #ifdef L_tmpnam
      static char tname_buf[L_tmpnam];
      #else
      static char *tname_buf = NULL;
      #endif
       
      /*
       * Get a line of input from the user, not including any terminating
       * newline.
       */
      static int getline(char *s, int n, FILE *f)
      {
          register int i = 0;
       
          while (1) {
          s[i] = (char) fgetc(f);
       
          if (s[i] == CR) {
              s[i] = fgetc(f);
          }
       
          if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) {
              s[i] = '\0';
              return (feof(f) ? 1 : 0);
          }
          ++i;
          }
      }
       
      static void putline(FILE *f, char *l)
      {
          int x;
       
          for (x = 0; l[x]; x++) {
          fputc(l[x], f);
          }
          fputc('\n', f);
      }
       
      /*
       * Make a password record from the given information.  A zero return
       * indicates success; failure means that the output buffer contains an
       * error message instead.
       */
      static int mkrecord(char *user, char *record, size_t rlen, char *passwd,
                  int alg)
      {
          char *pw;
          char cpw[120];
          char pwin[MAX_STRING_LEN];
          char pwv[MAX_STRING_LEN];
          char salt[9];
       
          if (passwd != NULL) {
          pw = passwd;
          }
          else {
      #ifdef TPF
              fprintf(stderr, "Invalid entry. The -b option is required on TPF.\n");
              return usage();
      #else
          if (ap_getpass("New password: ", pwin, sizeof(pwin)) != 0) {
              ap_snprintf(record, (rlen - 1), "password too long (>%lu)",
                  (unsigned long) (sizeof(pwin) - 1));
              return ERR_OVERFLOW;
          }
          ap_getpass("Re-type new password: ", pwv, sizeof(pwv));
          if (strcmp(pwin, pwv) != 0) {
              ap_cpystrn(record, "password verification error", (rlen - 1));
              return ERR_PWMISMATCH;
          }
          pw = pwin;
              memset(pwv, '\0', sizeof(pwin));
      #endif /* TPF */
          }
          switch (alg) {
       
          case ALG_APSHA:
          /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */
          ap_sha1_base64(pw,strlen(pw),cpw);
          break;
       
          case ALG_APMD5:
              (void) srand((int) time((time_t *) NULL));
              ap_to64(&salt[0], rand(), 8);
              salt[8] = '\0';
       
          ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
                   cpw, sizeof(cpw));
          break;
       
          case ALG_PLAIN:
          /* XXX this len limitation is not in sync with any HTTPd len. */
          ap_cpystrn(cpw,pw,sizeof(cpw));
          break;
       
          case ALG_CRYPT:
          default:
              (void) srand((int) time((time_t *) NULL));
              ap_to64(&salt[0], rand(), 8);
              salt[8] = '\0';
       
          ap_cpystrn(cpw, (char *)crypt(pw, salt), sizeof(cpw) - 1);
          break;
          }
          memset(pw, '\0', strlen(pw));
       
          /*
           * Check to see if the buffer is large enough to hold the username,
           * hash, and delimiters.
           */
          if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) {
          ap_cpystrn(record, "resultant record too long", (rlen - 1));
          return ERR_OVERFLOW;
          }
          strcpy(record, user);
          strcat(record, ":");
          strcat(record, cpw);
          return 0;
      }
       
      static int usage(void)
      {
          fprintf(stderr, "Usage:\n");
          fprintf(stderr, "\thtpasswd [-cmdps] passwordfile username\n");
          fprintf(stderr, "\thtpasswd -b[cmdps] passwordfile username password\n\n");
          fprintf(stderr, "\thtpasswd -n[mdps] username\n");
          fprintf(stderr, "\thtpasswd -nb[mdps] username password\n");
          fprintf(stderr, " -c  Create a new file.\n");
          fprintf(stderr, " -n  Don't update file; display results on stdout.\n");
          fprintf(stderr, " -m  Force MD5 encryption of the password"
      #if defined(WIN32) || defined(TPF) || defined(NETWARE)
          " (default)"
      #endif
          ".\n");
          fprintf(stderr, " -d  Force CRYPT encryption of the password"
      #if (!(defined(WIN32) || defined(TPF) || defined(NETWARE)))
              " (default)"
      #endif
              ".\n");
          fprintf(stderr, " -p  Do not encrypt the password (plaintext).\n");
          fprintf(stderr, " -s  Force SHA encryption of the password.\n");
          fprintf(stderr, " -b  Use the password from the command line rather "
              "than prompting for it.\n");
          fprintf(stderr,
              "On Windows, TPF and NetWare systems the '-m' flag is used by default.\n");
          fprintf(stderr,
              "On all other systems, the '-p' flag will probably not work.\n");
          return ERR_SYNTAX;
      }
       
      static void interrupted(void)
      {
          fprintf(stderr, "Interrupted.\n");
          if (tempfilename != NULL) {
          unlink(tempfilename);
          }
          exit(ERR_INTERRUPTED);
      }
       
      /*
       * Check to see if the specified file can be opened for the given
       * access.
       */
      static int accessible(char *fname, char *mode)
      {
          FILE *s;
       
          s = fopen(fname, mode);
          if (s == NULL) {
          return 0;
          }
          fclose(s);
          return 1;
      }
       
      /*
       * Return true if a file is readable.
       */
      static int readable(char *fname)
      {
          return accessible(fname, "r");
      }
       
      /*
       * Return true if the specified file can be opened for write access.
       */
      static int writable(char *fname)
      {
          return accessible(fname, "a");
      }
       
      /*
       * Return true if the named file exists, regardless of permissions.
       */
      static int exists(char *fname)
      {
      #ifdef WIN32
          struct _stat sbuf;
      #else
          struct stat sbuf;
      #endif
          int check;
       
      #ifdef WIN32
          check = _stat(fname, &sbuf);
      #else
          check = stat(fname, &sbuf);
      #endif
          return ((check == -1) && (errno == ENOENT)) ? 0 : 1;
      }
       
      /*
       * Copy from the current position of one file to the current position
       * of another.
       */
      static void copy_file(FILE *target, FILE *source)
      {
          static char line[MAX_STRING_LEN];
       
          while (fgets(line, sizeof(line), source) != NULL) {
          fputs(line, target);
          }
      }
       
      /*
       * Let's do it.  We end up doing a lot of file opening and closing,
       * but what do we care?  This application isn't run constantly.
       */
      int main(int argc, char *argv[])
      {
          FILE *ftemp = NULL;
          FILE *fpw = NULL;
          char user[MAX_STRING_LEN];
          char password[MAX_STRING_LEN];
          char record[MAX_STRING_LEN];
          char line[MAX_STRING_LEN];
          char pwfilename[MAX_STRING_LEN];
          char *arg;
          int found = 0;
          int alg = ALG_CRYPT;
          int newfile = 0;
          int nofile = 0;
          int noninteractive = 0;
          int i;
          int args_left = 2;
       
          tempfilename = NULL;
          signal(SIGINT, (void (*)(int)) interrupted);
       
          /*
           * Preliminary check to make sure they provided at least
           * three arguments, we'll do better argument checking as
           * we parse the command line.
           */
          if (argc < 3) {
          return usage();
          }
       
          /*
           * Go through the argument list and pick out any options.  They
           * have to precede any other arguments.
           */
          for (i = 1; i < argc; i++) {
          arg = argv[i];
          if (*arg != '-') {
              break;
          }
          while (*++arg != '\0') {
              if (*arg == 'c') {
              newfile++;
              }
              else if (*arg == 'n') {
              nofile++;
              args_left--;
              }
              else if (*arg == 'm') {
              alg = ALG_APMD5;
              }
              else if (*arg == 's') {
              alg = ALG_APSHA;
              }
              else if (*arg == 'p') {
              alg = ALG_PLAIN;
              }
              else if (*arg == 'd') {
              alg = ALG_CRYPT;
              }
              else if (*arg == 'b') {
              noninteractive++;
              args_left++;
              }
              else {
              return usage();
              }
          }
          }
       
          /*
           * Make sure we still have exactly the right number of arguments left
           * (the filename, the username, and possibly the password if -b was
           * specified).
           */
          if ((argc - i) != args_left) {
          return usage();
          }
      #ifdef NETWARE
          UnAugmentAsterisk(TRUE);
          SetCurrentNameSpace(NW_NS_LONG);
          SetTargetNameSpace(NW_NS_LONG);
      #endif
          if (newfile && nofile) {
          fprintf(stderr, "%s: -c and -n options conflict\n", argv[0]);
          return ERR_SYNTAX;
          }
          if (nofile) {
          i--;
          }
          else {
          if (strlen(argv[i]) > (sizeof(pwfilename) - 1)) {
              fprintf(stderr, "%s: filename too long\n", argv[0]);
              return ERR_OVERFLOW;
          }
          strcpy(pwfilename, argv[i]);
          if (strlen(argv[i + 1]) > (sizeof(user) - 1)) {
              fprintf(stderr, "%s: username too long (>%lu)\n", argv[0],
                  (unsigned long)(sizeof(user) - 1));
              return ERR_OVERFLOW;
          }
          }
          strcpy(user, argv[i + 1]);
          if ((arg = strchr(user, ':')) != NULL) {
          fprintf(stderr, "%s: username contains illegal character '%c'\n",
              argv[0], *arg);
          return ERR_BADUSER;
          }
          if (noninteractive) {
          if (strlen(argv[i + 2]) > (sizeof(password) - 1)) {
              fprintf(stderr, "%s: password too long (>%lu)\n", argv[0],
                  (unsigned long)(sizeof(password) - 1));
              return ERR_OVERFLOW;
          }
          strcpy(password, argv[i + 2]);
          }
       
      #ifdef WIN32
          if (alg == ALG_CRYPT) {
          alg = ALG_APMD5;
          fprintf(stderr, "Automatically using MD5 format on Windows.\n");
          }
      #elif defined(TPF) || defined(NETWARE)
          if (alg == ALG_CRYPT) {
              alg = ALG_APMD5;
              fprintf(stderr, "Automatically using MD5 format.\n");
           }
      #endif
       
      #if (!(defined(WIN32) || defined(TPF) || defined(NETWARE)))
          if (alg == ALG_PLAIN) {
          fprintf(stderr,"Warning: storing passwords as plain text might "
              "just not work on this platform.\n");
          }
      #endif
          if (! nofile) {
          /*
           * Only do the file checks if we're supposed to frob it.
           *
           * Verify that the file exists if -c was omitted.  We give a special
           * message if it doesn't.
           */
          if ((! newfile) && (! exists(pwfilename))) {
              fprintf(stderr,
                  "%s: cannot modify file %s; use '-c' to create it\n",
                  argv[0], pwfilename);
              perror("fopen");
              exit(ERR_FILEPERM);
          }
          /*
           * Verify that we can read the existing file in the case of an update
           * to it (rather than creation of a new one).
           */
          if ((! newfile) && (! readable(pwfilename))) {
              fprintf(stderr, "%s: cannot open file %s for read access\n",
                  argv[0], pwfilename);
              perror("fopen");
              exit(ERR_FILEPERM);
          }
          /*
           * Now check to see if we can preserve an existing file in case
           * of password verification errors on a -c operation.
           */
          if (newfile && exists(pwfilename) && (! readable(pwfilename))) {
              fprintf(stderr, "%s: cannot open file %s for read access\n"
                  "%s: existing auth data would be lost on "
                  "password mismatch",
                  argv[0], pwfilename, argv[0]);
              perror("fopen");
              exit(ERR_FILEPERM);
          }
          /*
           * Now verify that the file is writable!
           */
          if (! writable(pwfilename)) {
              fprintf(stderr, "%s: cannot open file %s for write access\n",
                  argv[0], pwfilename);
              perror("fopen");
              exit(ERR_FILEPERM);
          }
          }
       
          /*
           * All the file access checks (if any) have been made.  Time to go to work;
           * try to create the record for the username in question.  If that
           * fails, there's no need to waste any time on file manipulations.
           * Any error message text is returned in the record buffer, since
           * the mkrecord() routine doesn't have access to argv[].
           */
          i = mkrecord(user, record, sizeof(record) - 1,
               noninteractive ? password : NULL,
               alg);
          if (i != 0) {
          fprintf(stderr, "%s: %s\n", argv[0], record);
          exit(i);
          }
          if (nofile) {
          printf("%s\n", record);
          exit(0);
          }
       
          /*
           * We can access the files the right way, and we have a record
           * to add or update.  Let's do it..
           */
          errno = 0;
          tempfilename = tmpnam(tname_buf);
          if ((tempfilename == NULL) || (*tempfilename == '\0')) {
          fprintf(stderr, "%s: unable to generate temporary filename\n",
              argv[0]);
          if (errno == 0) {
              errno = ENOENT;
          }
          perror("tmpnam");
          exit(ERR_FILEPERM);
          }
          ftemp = fopen(tempfilename, "w+");
          if (ftemp == NULL) {
          fprintf(stderr, "%s: unable to create temporary file '%s'\n", argv[0],
              tempfilename);
          perror("fopen");
          exit(ERR_FILEPERM);
          }
          /*
           * If we're not creating a new file, copy records from the existing
           * one to the temporary file until we find the specified user.
           */
          if (! newfile) {
          char scratch[MAX_STRING_LEN];
       
          fpw = fopen(pwfilename, "r");
          while (! (getline(line, sizeof(line), fpw))) {
              char *colon;
       
              if ((line[0] == '#') || (line[0] == '\0')) {
              putline(ftemp, line);
              continue;
              }
              strcpy(scratch, line);
              /*
               * See if this is our user.
               */
              colon = strchr(scratch, ':');
              if (colon != NULL) {
              *colon = '\0';
              }
              if (strcmp(user, scratch) != 0) {
              putline(ftemp, line);
              continue;
              }
              found++;
              break;
          }
          }
          if (found) {
          fprintf(stderr, "Updating ");
          }
          else {
          fprintf(stderr, "Adding ");
          }
          fprintf(stderr, "password for user %s\n", user);
          /*
           * Now add the user record we created.
           */
          putline(ftemp, record);
          /*
           * If we're updating an existing file, there may be additional
           * records beyond the one we're updating, so copy them.
           */
          if (! newfile) {
          copy_file(ftemp, fpw);
          fclose(fpw);
          }
          /*
           * The temporary file now contains the information that should be
           * in the actual password file.  Close the open files, re-open them
           * in the appropriate mode, and copy them file to the real one.
           */
          fclose(ftemp);
          fpw = fopen(pwfilename, "w+");
          ftemp = fopen(tempfilename, "r");
          copy_file(fpw, ftemp);
          fclose(fpw);
          fclose(ftemp);
          unlink(tempfilename);
          return 0;
      }


    Эта тема была разделена из темы "Что это за ошибка?"
      Посмотрю сегодня (23.01.06).
      Все таки оригинальнй был "Турбо Паскаль", очень на Си смахивал ;)
        Спасибо. ЖДУ!!!
          Цитата nekto550 @

          Нужная мне обработка похоже тут: ALG_APMD5...

          Все верно, именно там пес и зарыт.
          Вот перевод этой части:
          ExpandedWrap disabled
               {case} ALG_APMD5:
                    // (void) srand((int) time((time_t *) NULL));
                    // srand - инициализация генератора псевдослучайных чисел: аналог на Паскале randomize;
                    // time  - возвращает текущее время;
                    //
                    randomize;
             
                    // ap_to64: функция из заголовков Apach;
                    // возвращает хеш - строковое представление длиной 8 символов случайного числа rand();
                    //
                    ap_to64(&salt[0], rand(), 8);
                    salt[8] = '\0'; // получение Ascii-z строки - добавление последнего нолика-конца строки
             
                    // ap_MD5Encode: шифрует пароль pw, используя хеш-строку salt;
                    // возвращает строку в cpw - это зашифрованный пароль и его надо использовать,
                    // его-то и записываем потом в файл ключей, чтобы с ним (зашифрованным) сравнивать
                    // проверяемый пароль для доступа (потом);
                    // salt: хеш для генерации пароля;
                    // здесь pw: незашифрованный пароль из командной строки, если он в ней задан,
                    // либо непросредственно введеный с клавиатуры (см. немного выше "ap_getpass(... pwin)");
                    // После выполнения cpw, насколько я понял, будет содержать в начале "магическую" строку:
                    //    AP_MD5PW_ID = "$apr1$",
                    // а уже после нее сам входной хеш (salt) и сгенерированное шифрованное значение.
                    // Это сделано для того, чтобы можно было в качестве salt подставлять либо исходный
                    // хеш, либо уже зашифрованный пароль (к котором тоже будет хеш);
                    //
                    ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
                         cpw, sizeof(cpw));


          Далее смотри место после конструкции "case":
          ExpandedWrap disabled
                // блок "REC"
                strcpy(record, user);
                strcat(record, ":");
                strcat(record, cpw);


          здесь в record cформируется строка вида: <нешифрованное имя пользователя>:<шифрованный пароль>.

          Для проверки пароля надо вызвать ap_MD5Encode еще раз.

          Я посмотрел в inet, нашел прогу сравнения на Си.
          Пощажу тему :) и приведу только перевод на "человечий" язык Delphi:
          ExpandedWrap disabled
            //==========================================================
            // определения из MD5
            //==========================================================
            (*
            const
               // "магическая" строка MD5 (метка о "зашифрованности")
               //
               AP_MD5PW_ID = '$apr1$';
               AP_MD5PW_IDLEN = 6;
             
            procedure ap_MD5Encode( password, hash, res: PChar; nbytes: integer );
             
            *)
             
            //==========================================================
            // MD5_PSW_Validate
            //==========================================================
            (*
             MD5_PSW_Validate: проверить соответствие пароля ChkPsw хешу hash.
             Шифрование MD5.
             Хеш hash должен быть уже "зашифрован"
             
             Вернет True если пароль верен и False иначе.
            *)
             
            function MD5_PSW_Validate( ChkPsw, hash: PChar ) : boolean;
            var
               // 512 - размер шифрованной строки, зависит от "длины ключа"
               // здесь взят для примера, в Си он быд всего 120;
               //
               sample: array [0..511] of char;
            begin
               Result := False;
             
               // если хеш строка не начинается с "магической" - неверно
               if StrLComp( hash, AP_MD5PW_ID, AP_MD5PW_IDLEN) <> 0 then
                  {неверно, хеш не зашифрован} Exit;
             
               // выполняем MD5-шифрование пароля
                 ap_MD5Encode( ChkPsw, hash, sample, sizeof(sample));
             
               // если строки совпадают -> OK
               Result := StrComp( sample, hash ) = 0;
            end;

          При проверке надо иметь в виду, что hash на входе должен содержать только шифро-часть той строки, которая возвращаена в record'е
          (метка 'блок "REC"'). Т.е. после двоеточия.

          Надеюсь понятно.
          Если что - спрашивай.
            Спасибо большое. Я наверное полностью обнаглел , но это вызвано моим незнанием.... Можно попросить немного переделать
            Чтобы вызывалась функция в неё из переменной 1 поступал логин а из переменной 2 пароль а она в переменную 3 выкидывала готовое (логин:шифрпароль)

            Слабоват я в программировании
              Тогда уж обе процы - шифровка и проверка.
              И, видимо, тебе удобнее если типы string вместо PChar.
              Примерно так:
              ExpandedWrap disabled
                //==========================================================
                // определения из MD5
                //==========================================================
                (*
                const
                   // "магическая" строка MD5 (метка о "зашифрованности")
                   //
                   AP_MD5PW_ID = '$apr1$';
                   AP_MD5PW_IDLEN = 6;
                 
                procedure ap_MD5Encode( password, hash, res: PChar; szRes: integer );
                procedure ap_to64( lpS: PChar; v: DWORD; n: integer );
                *)
                 
                //==========================================================
                // "тутошние" определения
                //==========================================================
                type
                   // 512 - размер шифрованной строки, зависит от "длины ключа"
                   // здесь взят для примера, в Си он был всего 120;
                   //
                   TMD5_PswBuffer = array [0..511] of char;
                 
                //==========================================================
                // MD5_Encode
                //==========================================================
                (*
                 MD5_Encode: выполнить MD5-шифрование для пользователя sUser с паролем
                 sPsw и получить строку sCoded вида:
                 
                  <Пользователь>:<Зашифрованная часть>
                 
                 Таблица соответствий для Си варианта:
                   static int mkrecord(char *user, char *record, size_t rlen, char *sPasswd, int alg)
                 
                 -------------------------------------
                   Си       Здесь
                 -------------------------------------
                   user     sUser
                   record   sCoded
                   rlen     убран
                   passwd   sPasswd
                   alg      убран, всегда MD5
                 -------------------------------------
                *)
                procedure MD5_Encode( const sUser, sPasswd: AnsiString; var sCoded: AnsiString );
                var
                   salt: array[0..8] of char;
                   cpw: TMD5_PswBuffer;
                begin
                   // randomize; - каждый раз вызывать не требуется, надо вызвать только
                   // один раз в начале выполнения программы или в FormCreate;
                   //
                 
                   // ap_to64: функция из заголовков Apach;
                   // возвращает хеш - строковое представление длиной 8 символов случайного числа rand();
                   //
                   ap_to64( @salt, trunc(random), 8);
                   salt[8] := #0; // получение Ascii-z строки - добавление последнего нолика-конца строки
                 
                   // ap_MD5Encode: шифрует пароль pw, используя хеш-строку salt;
                   // возвращает строку в cpw - это зашифрованный пароль и его надо использовать,
                   // его-то и записываем потом в файл ключей, чтобы с ним (зашифрованным) сравнивать
                   // проверяемый пароль для доступа (потом);
                   // salt: хеш для генерации пароля;
                   // здесь pw: незашифрованный пароль из командной строки, если он в ней задан,
                   // либо непросредственно введеный с клавиатуры (см. немного выше "ap_getpass(... pwin)");
                   // После выполнения cpw, насколько я понял, будет содержать в начале "магическую" строку:
                   //    AP_MD5PW_ID = "$apr1$",
                   // а уже после нее сам входной хеш (salt) и сгенерированное шифрованное значение.
                   //
                   ap_MD5Encode( PChar(sPasswd), salt, cpw, sizeof(cpw));
                 
                   // получение строки: <ползователь>:<зашифрованная часть>
                   //
                   sCoded := sUser + ':' + cpw;
                end; // MD5_Encode
                 
                //==========================================================
                // MD5_PSW_Validate
                //==========================================================
                (*
                 MD5_PSW_Validate: проверить соответствие пароля sChkPsw хешу sUserHash.
                 Шифрование MD5.
                 
                 Хеш sUserHash должен быть уже "зашифрован" и имеет вид:
                 
                 <ползователь>:<зашифрованная часть>, т.е. полученный функцией MD5_Encode
                 либо только <зашифрованная часть>.
                 
                 Вернет True если пароль верен и False иначе.
                *)
                function MD5_PSW_Validate( sChkPsw, sUserHash: AnsiString) : boolean;
                var
                   sample: TMD5_PswBuffer;
                   i: integer;
                begin
                   Result := False;
                 
                   // выделим их строки sUserHash только зашифрованную часть...
                   //
                   i:= Pos( ':', sUserHash );
                   if i <> 0 then
                      // уберем имя пользователя - нам не требуется (!), имеет
                      // значение только пароль.
                      system.delete( sUserhash, 1, i ); // убрать все от начала до двоеточия (вкл его)
                 
                   // если хеш строка не начинается с "магической" - неверно
                   if StrLComp( PChar(sUserHash), AP_MD5PW_ID, AP_MD5PW_IDLEN) <> 0 then
                      {неверно, хеш не зашифрован} Exit;
                 
                   // выполняем MD5-шифрование входного пароля
                   ap_MD5Encode( PChar(sChkPsw), PChar(sUserHash), {out}sample, sizeof(sample));
                 
                   // если строки совпадают -> OK
                   Result := StrComp( sample, PChar(sUserHash) ) = 0;
                end; // MD5_PSW_Validate
                 
                // пример работы:
                procedure Form1.FormCreate( Sender: TObject);
                begin
                   randomize;
                 
                   {... другой код...}
                end;
                 
                // проверка пароля / получение пароля
                // в реальной проге будет две процедуры - одна создает, другая проверяет;
                //
                procedure Form1.BtnCheckPassword( Sender: TObject);
                var sRes: AnsiString; // зашифрованная строка
                begin
                  
                   // I) получить готовую MD5-строку ключа для пользователя
                   // с именем "user" и паролем "куКиШ"
                   //
                   MD5_Encode( 'user', 'куКиШ', sRes );
                   { здесь sRes имеет вид: <имя пользователя>:<шифр> }
                 
                   // ... что-то еще ...
                 
                   // II) проверить подходит ли пароль 'Test' для строки sRes
                   //
                   if not MD5_PSW_Validate( 'Test', sRes) then
                   begin
                      // Raise Exception.Create( 'Неверный пароль' )
                      ShowMessage('Неверный пароль' )
                   end else
                   begin // подходит
                      ShowMessage('Доступ разрешен' )
                   end;
                end;
                Привет! Большое спасибо, но не работает... У меня компилятор вышибает от

                ExpandedWrap disabled
                  type
                   
                     TMD5_PswBuffer = array [0..511] of char;

                и если не трудно посмотри этот мой топик. Проблемы с кодировкой
                  Цитата nekto550 @
                  У меня компилятор вышибает от
                  type
                  TMD5_PswBuffer = array [0..511] of char;

                  А что за ошибка?

                  Это правильный код и если вышибает, значит скорее всего вставлено куда-то не туда.
                    Точно я ошибся. Исправил. Теперь другое

                    ExpandedWrap disabled
                       ap_to64( @salt, trunc(random), 8);


                    [Ошибка] Unit69.pas(211): Undeclared identifier: 'ap_to64'

                    Странно.... Как её задекларировать?
                      Упс.
                      А может быть у тебя нет также и функции ap_MD5Encode?
                      Чтобы это сразу проверить можешь просто временно закоментировать строку с ap_to64.
                      P.S. А у тебя есть ICQ? Если есть стучи мне на мой. В привате выслал.
                        По просьбе AK666 выкладываю модуль шифрования и небольшое тестовое приложение.
                        Прикреплённый файлПрикреплённый файлcrypts.zip (61.32 Кбайт, скачиваний: 155)

                        Добавлено
                        Однако, давно это было - почти пять лет как )
                          Цитата RuSA @
                          выкладываю модуль шифрования и небольшое тестовое приложение

                          СПАСИБО огороменное!


                          Цитата RuSA @
                          Однако, давно это было - почти пять лет как )

                          и тем не менее....
                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0.1004 ]   [ 17 queries used ]   [ Generated: 24.10.26, 05:44 GMT ]