123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /* crypt.h -- base code for traditional PKWARE encryption
- Version 1.2.0, September 16th, 2017
- Copyright (C) 2012-2017 Nathan Moinvaziri
- https://github.com/nmoinvaz/minizip
- Copyright (C) 1998-2005 Gilles Vollant
- Modifications for Info-ZIP crypting
- http://www.winimage.com/zLibDll/minizip.html
- Copyright (C) 2003 Terry Thorsen
- This code is a modified version of crypting code in Info-ZIP distribution
- Copyright (C) 1990-2000 Info-ZIP. All rights reserved.
- This program is distributed under the terms of the same license as zlib.
- See the accompanying LICENSE file for the full text of the license.
- */
- #ifndef _MINICRYPT_H
- #define _MINICRYPT_H
- #include <stdint.h>
- #include <stdlib.h>
- #include <time.h>
- # ifndef ZCR_SEED2
- # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
- # endif
- #if ZLIB_VERNUM < 0x1270
- typedef unsigned long z_crc_t;
- #endif
- #define RAND_HEAD_LEN 12
- /***************************************************************************/
- #define CRC32(c, b) ((*(pcrc_32_tab+(((uint32_t)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
- /***************************************************************************/
- #define zdecode(pkeys,pcrc_32_tab,c) \
- (update_keys(pkeys,pcrc_32_tab, c ^= decrypt_byte(pkeys)))
- #define zencode(pkeys,pcrc_32_tab,c,t) \
- (t = decrypt_byte(pkeys), update_keys(pkeys,pcrc_32_tab,c), t^(c))
- /***************************************************************************/
- /* Return the next byte in the pseudo-random sequence */
- static uint8_t decrypt_byte(uint32_t *pkeys)
- {
- unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
- * unpredictable manner on 16-bit systems; not a problem
- * with any known compiler so far, though */
- temp = ((uint32_t)(*(pkeys + 2)) & 0xffff) | 2;
- return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
- }
- /* Update the encryption keys with the next byte of plain text */
- static uint8_t update_keys(uint32_t *pkeys, const z_crc_t *pcrc_32_tab, int32_t c)
- {
- (*(pkeys + 0)) = (uint32_t)CRC32((*(pkeys + 0)), c);
- (*(pkeys + 1)) += (*(pkeys + 0)) & 0xff;
- (*(pkeys + 1)) = (*(pkeys + 1)) * 134775813L + 1;
- {
- int32_t keyshift = (int32_t)((*(pkeys + 1)) >> 24);
- (*(pkeys + 2)) = (uint32_t)CRC32((*(pkeys + 2)), keyshift);
- }
- return c;
- }
- /* Initialize the encryption keys and the random header according to the given password. */
- static void init_keys(const char *passwd, uint32_t *pkeys, const z_crc_t *pcrc_32_tab)
- {
- *(pkeys + 0) = 305419896L;
- *(pkeys + 1) = 591751049L;
- *(pkeys + 2) = 878082192L;
- while (*passwd != 0)
- {
- update_keys(pkeys, pcrc_32_tab, *passwd);
- passwd += 1;
- }
- }
- #ifndef NOCRYPT
- /* Generate cryptographically secure random numbers */
- static int cryptrand(unsigned char *buf, unsigned int len)
- {
- /*
- Important This API is deprecated. New and existing software should
- start using Cryptography Next Generation APIs.
- Microsoft may remove this API in future releases.
- see: https://docs.microsoft.com/zh-cn/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom
- */
- #define CRYPTGENRANDOM_DEPRECATED 1
- #if defined(_WIN32) && !defined(CRYPTGENRANDOM_DEPRECATED)
- HCRYPTPROV provider;
- unsigned __int64 pentium_tsc[1];
- int rlen = 0;
- int result = 0;
- if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- {
- result = CryptGenRandom(provider, len, buf);
- CryptReleaseContext(provider, 0);
- if (result)
- return len;
- }
- for (rlen = 0; rlen < (int)len; ++rlen)
- {
- if (rlen % 8 == 0)
- QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc);
- buf[rlen] = ((unsigned char*)pentium_tsc)[rlen % 8];
- }
- return rlen;
- #else
- static unsigned calls = 0; /* ensure different random header each time */
- /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
- * output of rand() to get less predictability, since rand() is
- * often poorly implemented.
- */
- if (++calls == 1)
- {
- srand((unsigned)(time(NULL) ^ ZCR_SEED2));
- }
- for(unsigned int i = 0; i < len; ++i){
- buf[i] = rand() % 256;
- }
- return len;
- #endif
- }
- /* Create encryption header */
- static int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
- const z_crc_t *pcrc_32_tab, uint8_t verify1, uint8_t verify2)
- {
- uint8_t n = 0; /* index in random header */
- uint8_t header[RAND_HEAD_LEN - 2]; /* random header */
- uint16_t t = 0; /* temporary */
- if (buf_size < RAND_HEAD_LEN)
- return 0;
- init_keys(passwd, pkeys, pcrc_32_tab);
- /* First generate RAND_HEAD_LEN-2 random bytes. */
- cryptrand(header, RAND_HEAD_LEN - 2);
- /* Encrypt random header (last two bytes is high word of crc) */
- init_keys(passwd, pkeys, pcrc_32_tab);
- for (n = 0; n < RAND_HEAD_LEN - 2; n++)
- buf[n] = (uint8_t)zencode(pkeys, pcrc_32_tab, header[n], t);
- buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify1, t);
- buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify2, t);
- return n;
- }
- #endif
- /***************************************************************************/
- #endif
|