#include "stdafx.h"
#pragma hdrstop        
#include "common.h"
#include "crypt.h"
#include "dz_errs.h"

#undef _DZ_FILE_
#define _DZ_FILE_ DZ_CRYPT_CPP

//#include "ZipErr.h"
/* crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
 *
 * This code is not copyrighted and is put in the public domain.  The
 * encryption/decryption parts (as opposed to the non-echoing password
 * parts) were originally written in Europe; the whole file can there-
 * fore be freely distributed from any country except the USA.  If this
 * code is imported into the USA, it cannot be re-exported from from
 * there to another country.  (This restriction might seem curious, but
 * this is what US law requires.)
 */
/* This encryption code is a direct transcription of the algorithm from
 * Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
 * file (appnote.txt) is distributed with the PKZIP program (even in the
 * version without encryption capabilities).
 * This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
  ** distributed under LGPL license ** see license.txt for details
 */

/* For the encoding task used in Zip (and ZipCloak), we want to initialize
 * the crypt algorithm with some reasonably unpredictable bytes, see
 * the crypthead() function. The standard rand() library function is
 * used to supply these 'random' bytes, which in turn is initialized by
 * a srand() call. The srand() function takes an "unsigned" (at least 16bit)
 * seed value as argument to determine the starting point of the rand()
 * pseudo-random number generator.
 * This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with
 * Seed1 supplied by the current time (= "(unsigned)time()") and Seed2
 * as some (hopefully) nondeterministic bitmask. On many (most) systems,
 * we use some "process specific" number, as the PID or something similar,
 * but when nothing unpredictable is available, a fixed number may be
 * sufficient.
 * NOTE:
 * 1.) This implementation requires the availability of the following
 *     standard UNIX C runtime library functions: time(), rand(), srand().
 *     On systems where some of them are missing, the environment that
 *     incorporates the crypt routines must supply suitable replacement
 *     functions.
 * 2.) It is a very bad idea to use a second call to time() to set the
 *     "Seed2" number! In this case, both "Seed1" and "Seed2" would be
 *     (almost) identical, resulting in a (mostly) "zero" constant seed
 *     number passed to srand().
 *
 * The implementation environment defined in the "zip.h" header should
 * supply a reasonable definition for ZCR_SEED2 (an unsigned number; for
 * most implementations of rand() and srand(), only the lower 16 bits are
 * significant!). An example that works on many systems would be
 *      "#define ZCR_SEED2  (unsigned)getpid()".
 * The default definition for ZCR_SEED2 supplied below should be regarded
 * as a fallback to allow successful compilation in "beta state"
 * environments.
 *

  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.

  See the accompanying file LICENSE, version 2007-Mar-4 or later
  (the contents of which are also included in zip.h) for terms of use.
  If, for some reason, all these files are missing, the Info-ZIP license
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html

  parts Copyright (C) 1997 Mike White, Eric W. Engler
************************************************************************
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht

   This file is part of TZipMaster Version 1.9.

    TZipMaster is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    TZipMaster 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.

    contact: problems@delphizip.org (include ZipMaster in the subject).
    updates: http://www.delphizip.org
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip 
************************************************************************/

// "last resort" source for second part of crypt seed pattern
#ifndef ZCR_SEED2 // RCV: Is now defined in Zip.h
#define ZCR_SEED2 (unsigned)3141592654L // use PI as default pattern
#endif

#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xFF] ^ ((c) >> 8))

// Return the next byte in the pseudo-random sequence
int _fastcall decrypt_byte(Keys keys)
{
    unsigned  temp;
    temp = ((unsigned)keys[2] & 0xFFFF) | 2;
    return (int)(((temp *(temp ^ 1)) >> 8) & 0xFF);
}

// Update the encryption keys with the next byte of plain text c :: Byte of
//   plain text.
int  _fastcall update_keys(int c, Keys keys)
{
    keys[0] = CRC32(keys[0], c);
    keys[1] += keys[0] & 0xFF;
    keys[1] = keys[1] * 134775813L + 1;
    {
        register int  keyshift = (int)(keys[1] >> 24);
        keys[2] = CRC32(keys[2], keyshift);
    }

    return c;
}

// Initialize the encryption keys and the random header according to the
//   given password. passwd :: Password string with which to modify keys.
void _fastcall init_keys(const char *passwd, Keys keys)
{
    keys[0] = 305419896L;
    keys[1] = 591751049L;
    keys[2] = 878082192L;

    while (*passwd != '\0')
    {
        update_keys((int) *passwd, keys);
        passwd++;
    }
}

int _fastcall zencode(int c, Keys keys)
{
    int t;
    unsigned  temp;
    temp = ((unsigned)keys[2] & 0xFFFF) | 2;
    t = (int)(((temp * (temp ^ 1)) >> 8) & 0xFF);

    keys[0] = CRC32(keys[0], c);
    keys[1] += keys[0] & 0xFF;
    keys[1] = keys[1] * 134775813L + 1;
    {
        register int  keyshift = (int)(keys[1] >> 24);
        keys[2] = CRC32(keys[2], keyshift);
    }

    return t ^ c;
}

int _fastcall zdecode(int c, Keys keys)
{
    int t;
    unsigned  temp;
    temp = ((unsigned)keys[2] & 0xFFFF) | 2;
    t = (int)(((temp * (temp ^ 1)) >> 8) & 0xFF);
    t ^= c;
    keys[0] = CRC32(keys[0], t);
    keys[1] += keys[0] & 0xFF;
	keys[1] = keys[1] * 134775813L + 1;
    {
        register int  keyshift = (int)(keys[1] >> 24);
        keys[2] = CRC32(keys[2], keyshift);
    }

    return t;
}




