First Kindle 4 PC solution

This commit is contained in:
Bart Simpson 2009-12-28 22:02:00 +00:00 committed by Apprentice Alf
parent 1f968255fe
commit 049f44231c
9 changed files with 1992 additions and 0 deletions

21
skindle/Makefile Normal file
View file

@ -0,0 +1,21 @@
OBJS=skindle.o md5.o sha1.o b64.o
CC=gcc
LD=gcc
EXE=skindle
EXTRALIBS=-lCrypt32
#use the following to strip your binary
LDFLAGS=-s
all: $(EXE)
%.o: %.c
$(CC) -c $(CFLAGS) $(INC) $< -o $@
$(EXE): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(EXTRALIBS)
clean:
-@rm *.o

78
skindle/README.txt Normal file
View file

@ -0,0 +1,78 @@
/*
Copyright 2010 BartSimpson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* Dependencies: none
* build on cygwin: gcc -o skindle skindle.c md5.c sha1.c b64.c -lCrypt32
* Under cygwin, you can just type make to build it.
* While the binary builds if you use the -mno-cygwin switch, it fails to
* work for some reason. The code should compile with Visual Studio, just
* add all the files to a project and add the Crypt32.lib dependency and
* it should build as a Win32 console app.
*/
/*
* MUST be run on the computer on which KindleForPC is installed
* under the account that was used to purchase DRM'ed content.
* Requires your kindle.info file which can be found in something like:
* <User home>\...\Amazon\Kindle For PC\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}
* where ... varies by platform but is "Local Settings\Application Data" on XP
*/
/*
What: KindleForPC DRM removal utility to preserve your fair use rights!
Why: Fair use is a well established doctrine, and I am no fan of vendor
lockin.
How: This utility implements the PID extraction, DRM key generation and
decryption algorithms employed by the KindleForPC application. This
is a stand alone app that does not require you to determine a PID on
your own, and it does not need to run KindleForPC in order to extract
any data from memory.
Shoutz: The DarkReverser - thanks for mobidedrm! The last part of this
is just a C port of mobidedrm.
labba and I<3cabbages for motivating me to do this the right way.
You guys shouldn't need to spend all your time responding to all the
changes Amazon is going to force you to make in unswindle each time
the release a new version.
Lawrence Lessig - You are my hero. 'Nuff said.
Thumbs down: Disney, MPAA, RIAA - you guys suck. Making billions off
of the exploitation of works out of copyright while vigourously
pushing copyright extension to prevent others from doing the same
is the height of hypocrasy.
Congress - you guys suck too. Why you arrogant pricks think you
are smarter than the founding fathers is beyond me.
*/
Rationale:
Need a tool to enable fair use of purchased ebook content.
Need a tool that is not dependent on any particular version of
KindleForPC and that does not need to run KindleForPC in order to
extract a PID. The tool documents the structure of the kindle.info
file and the data and algorthims that are used to derive per book
PID values.
Installing:
A cygwin compatable binary is included. You need a minimal cygwin
installation in order to run it. To build from source, you will need
cygwin with gcc and make. This has not been tested with Visual Studio.
Usage:
./skindle <drm'ed prc file> <name of output file> <kindle.info path>
You need to locate your kindle.info file somewhere on your system.
You can copy it to a local directory, but you need to refer to it
each time you run skindle.

80
skindle/b64.c Normal file
View file

@ -0,0 +1,80 @@
/*********************************************************************\
LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
VERSION HISTORY:
Bob Trower 08/04/01 -- Create Version 0.00.00B
\******************************************************************* */
#include <stdlib.h>
/*
** Translation Table as described in RFC1113
*/
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
** encodeblock
**
** encode 3 8-bit binary bytes as 4 '6-bit' characters
*/
void encodeblock(unsigned char in[3], unsigned char out[4], int len) {
out[0] = cb64[ in[0] >> 2 ];
out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}
/*
** encode
**
** base64 encode a stream adding padding and line breaks as per spec.
*/
unsigned int base64(unsigned char *inbuf, unsigned int len, unsigned char *outbuf) {
unsigned char in[3], out[4];
int c;
unsigned int i = 0;
unsigned int outlen = 0;
while (i < len) {
int n = 0;
for(c = 0; c < 3; c++, i++) {
if (i < len) {
in[c] = inbuf[i];
n++;
}
else {
in[c] = 0;
}
}
if (n) {
encodeblock(in, out, n);
for(c = 0; c < 4; c++) {
outbuf[outlen++] = out[c];
}
}
}
return outlen;
}

381
skindle/md5.c Normal file
View file

@ -0,0 +1,381 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[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
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

91
skindle/md5.h Normal file
View file

@ -0,0 +1,91 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

234
skindle/sha1.c Normal file
View file

@ -0,0 +1,234 @@
/*
sha1.c: Implementation of SHA-1 Secure Hash Algorithm-1
Based upon: NIST FIPS180-1 Secure Hash Algorithm-1
http://www.itl.nist.gov/fipspubs/fip180-1.htm
Non-official Japanese Translation by HIRATA Yasuyuki:
http://yasu.asuka.net/translations/SHA-1.html
Copyright (C) 2002 vi@nwr.jp. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgement in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as beging the original software.
3. This notice may not be removed or altered from any source distribution.
Note:
The copyright notice above is copied from md5.h by L. Peter Deutsch
<ghost@aladdin.com>. Thank him since I'm not a good speaker of English. :)
*/
#include <string.h>
#include "sha1.h"
/*
* Packing bytes to a word
*
* Should not assume p is aligned to word boundary
*/
static sha1_word_t packup(sha1_byte_t *p)
{
/* Portable, but slow */
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3] << 0;
}
/*
* Unpacking a word to bytes
*
* Should not assume p is aligned to word boundary
*/
static void unpackup(sha1_byte_t *p, sha1_word_t q)
{
p[0] = (q >> 24) & 0xff;
p[1] = (q >> 16) & 0xff;
p[2] = (q >> 8) & 0xff;
p[3] = (q >> 0) & 0xff;
}
/*
* Processing a block
*/
static void sha1_update_now(sha1_state_s *pms, sha1_byte_t *bp)
{
sha1_word_t tmp, a, b, c, d, e, w[16+16];
int i, s;
/* pack 64 bytes into 16 words */
for(i = 0; i < 16; i++) {
w[i] = packup(bp + i * sizeof(sha1_word_t));
}
memcpy(w + 16, w + 0, sizeof(sha1_word_t) * 16);
a = pms->sha1_h[0], b = pms->sha1_h[1], c = pms->sha1_h[2], d = pms->sha1_h[3], e = pms->sha1_h[4];
#define rot(x,n) (((x) << n) | ((x) >> (32-n)))
#define f0(b, c, d) ((b&c)|(~b&d))
#define f1(b, c, d) (b^c^d)
#define f2(b, c, d) ((b&c)|(b&d)|(c&d))
#define f3(b, c, d) (b^c^d)
#define k0 0x5a827999
#define k1 0x6ed9eba1
#define k2 0x8f1bbcdc
#define k3 0xca62c1d6
/* t=0-15 */
s = 0;
for(i = 0; i < 16; i++) {
tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
e = d; d = c; c = rot(b, 30); b = a; a = tmp;
s = (s + 1) % 16;
}
/* t=16-19 */
for(i = 16; i < 20; i++) {
w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
w[s+16] = w[s];
tmp = rot(a, 5) + f0(b, c, d) + e + w[s] + k0;
e = d; d = c; c = rot(b, 30); b = a; a = tmp;
s = (s + 1) % 16;
}
/* t=20-39 */
for(i = 0; i < 20; i++) {
w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
w[s+16] = w[s];
tmp = rot(a, 5) + f1(b, c, d) + e + w[s] + k1;
e = d; d = c; c = rot(b, 30); b = a; a = tmp;
s = (s + 1) % 16;
}
/* t=40-59 */
for(i = 0; i < 20; i++) {
w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
w[s+16] = w[s];
tmp = rot(a, 5) + f2(b, c, d) + e + w[s] + k2;
e = d; d = c; c = rot(b, 30); b = a; a = tmp;
s = (s + 1) % 16;
}
/* t=60-79 */
for(i = 0; i < 20; i++) {
w[s] = rot(w[s+13] ^ w[s+8] ^ w[s+2] ^ w[s], 1);
w[s+16] = w[s];
tmp = rot(a, 5) + f3(b, c, d) + e + w[s] + k3;
e = d; d = c; c = rot(b, 30); b = a; a = tmp;
s = (s + 1) % 16;
}
pms->sha1_h[0] += a, pms->sha1_h[1] += b, pms->sha1_h[2] += c, pms->sha1_h[3] += d, pms->sha1_h[4] += e;
}
/*
* Increment sha1_size1, sha1_size2 field of sha1_state_s
*/
static void incr(sha1_state_s *pms, int v)
{
sha1_word_t q;
q = pms->sha1_size1 + v * BITS;
if(q < pms->sha1_size1) {
pms->sha1_size2++;
}
pms->sha1_size1 = q;
}
/*
* Initialize sha1_state_s as FIPS specifies
*/
void sha1_init(sha1_state_s *pms)
{
memset(pms, 0, sizeof(*pms));
pms->sha1_h[0] = 0x67452301; /* Initialize H[0]-H[4] */
pms->sha1_h[1] = 0xEFCDAB89;
pms->sha1_h[2] = 0x98BADCFE;
pms->sha1_h[3] = 0x10325476;
pms->sha1_h[4] = 0xC3D2E1F0;
}
/*
* Fill block and update output when needed
*/
void sha1_update(sha1_state_s *pms, sha1_byte_t *bufp, int length)
{
/* Is the buffer partially filled? */
if(pms->sha1_count != 0) {
if(pms->sha1_count + length >= (signed) sizeof(pms->sha1_buf)) { /* buffer is filled enough */
int fil = sizeof(pms->sha1_buf) - pms->sha1_count; /* length to copy */
memcpy(pms->sha1_buf + pms->sha1_count, bufp, fil);
sha1_update_now(pms, pms->sha1_buf);
length -= fil;
bufp += fil;
pms->sha1_count = 0;
incr(pms, fil);
} else {
memcpy(pms->sha1_buf + pms->sha1_count, bufp, length);
pms->sha1_count += length;
incr(pms, length);
return;
}
}
/* Loop to update state */
for(;;) {
if(length < (signed) sizeof(pms->sha1_buf)) { /* Short to fill up the buffer */
if(length) {
memcpy(pms->sha1_buf, bufp, length);
}
pms->sha1_count = length;
incr(pms, length);
break;
}
sha1_update_now(pms, bufp);
length -= sizeof(pms->sha1_buf);
bufp += sizeof(pms->sha1_buf);
incr(pms, sizeof(pms->sha1_buf));
}
}
void sha1_finish(sha1_state_s *pms, sha1_byte_t output[SHA1_OUTPUT_SIZE])
{
int i;
sha1_byte_t buf[1];
/* fill a bit */
buf[0] = 0x80;
sha1_update(pms, buf, 1);
/* Decrement sha1_size1, sha1_size2 */
if((pms->sha1_size1 -= BITS) == 0) {
pms->sha1_size2--;
}
/* fill zeros */
if(pms->sha1_count > (signed) (sizeof(pms->sha1_buf) - 2 * sizeof(sha1_word_t))) {
memset(pms->sha1_buf + pms->sha1_count, 0, sizeof(pms->sha1_buf) - pms->sha1_count);
sha1_update_now(pms, pms->sha1_buf);
pms->sha1_count = 0;
}
memset(pms->sha1_buf + pms->sha1_count, 0,
sizeof(pms->sha1_buf) - pms->sha1_count - sizeof(sha1_word_t) * 2);
/* fill last length */
unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 2, pms->sha1_size2);
unpackup(pms->sha1_buf + sizeof(pms->sha1_buf) - sizeof(sha1_word_t) * 1, pms->sha1_size1);
/* final update */
sha1_update_now(pms, pms->sha1_buf);
/* move hash value to output byte array */
for(i = 0; i < (signed) (sizeof(pms->sha1_h)/sizeof(sha1_word_t)); i++) {
unpackup(output + i * sizeof(sha1_word_t), pms->sha1_h[i]);
}
}

68
skindle/sha1.h Normal file
View file

@ -0,0 +1,68 @@
/*
sha1.h: Implementation of SHA-1 Secure Hash Algorithm-1
Based upon: NIST FIPS180-1 Secure Hash Algorithm-1
http://www.itl.nist.gov/fipspubs/fip180-1.htm
Non-official Japanese Translation by HIRATA Yasuyuki:
http://yasu.asuka.net/translations/SHA-1.html
Copyright (C) 2002 vi@nwr.jp. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgement in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as beging the original software.
3. This notice may not be removed or altered from any source distribution.
Note:
The copyright notice above is copied from md5.h by L. Petet Deutsch
<ghost@aladdin.com>. Thank him since I'm not a good speaker of English. :)
*/
#ifndef SHA1_H
#define SHA1_H
typedef unsigned int sha1_word_t; /* 32bits unsigned integer */
typedef unsigned char sha1_byte_t; /* 8bits unsigned integer */
#define BITS 8
/* Define the state of SHA-1 algorithm */
typedef struct {
sha1_byte_t sha1_buf[64]; /* 512 bits */
int sha1_count; /* How many bytes are used */
sha1_word_t sha1_size1; /* Length counter Lower Word */
sha1_word_t sha1_size2; /* Length counter Upper Word */
sha1_word_t sha1_h[5]; /* Hash output */
} sha1_state_s;
#define SHA1_OUTPUT_SIZE 20 /* in bytes */
/* External Functions */
#ifdef __cplusplus
extern "C" {
#endif
/* Initialize SHA-1 algorithm */
void sha1_init(sha1_state_s *pms);
/* Append a string to SHA-1 algorithm */
void sha1_update(sha1_state_s *pms, sha1_byte_t *input_buffer, int length);
/* Finish the SHA-1 algorithm and return the hash */
void sha1_finish(sha1_state_s *pms, sha1_byte_t output[SHA1_OUTPUT_SIZE]);
#ifdef __cplusplus
}
#endif
#endif

1039
skindle/skindle.c Normal file

File diff suppressed because it is too large Load diff

BIN
skindle/skindle.exe Normal file

Binary file not shown.