/*******************************************************************************/
/* */
/* Copyright 2004 Pascal Gloor */
/* */
/* 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. */
/* */
/*******************************************************************************/
/* Author : Pascal Gloor <pascal.gloor@spale.com> */
/* Version : 1.0 */
/* Revision : 02.04.2005 */
#include <stdio.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include "scrypt.h"
#include "sha256.h"
#define BUFFER 16384
void sc_read(FILE *file, char *buf, size_t *len, int *end)
{
size_t clen;
clen = fread(buf+*len, 1, BUFFER-*len, file);
if ( clen == 0 )
{
if ( feof(file) == 0 )
{
fprintf(stderr,"fread(): %s\n",strerror(errno));
exit(EXIT_FAILURE);
}
else
{
*end = 1;
}
}
else
{
*len += clen;
}
}
void sc_send(FILE *file, char *buf, size_t *len)
{
size_t clen;
clen = fwrite(buf, 1, *len, file);
if ( clen == 0 && *len > 0 )
{
fprintf(stderr,"fwrite(): %s\n",strerror(errno));
exit(EXIT_FAILURE);
}
else
{
memmove(buf, buf+clen, *len-clen);
*len -= clen;
}
}
char sc_key(char *hash, uint32_t *cnum)
{
uint8_t m = *( hash + ( *cnum % 32 ) );
uint8_t c = (*cnum % 256);
uint16_t check = c + m;
return (check % 256);
}
void sc_work(char *ibuf, size_t *ilen, char *obuf, size_t *olen, char *hash, uint32_t *cnum)
{
size_t i;
if ( *ilen > (BUFFER-*olen) )
return;
for( i=0; i<*ilen; i++ )
{
*(obuf+*olen+i) = *(ibuf+i) ^ sc_key(hash, cnum);
*cnum += 1;
}
*olen += i;
memmove(ibuf, ibuf+i, *ilen-i);
*ilen -= i;
}
void main_loop(char *key, FILE *in, FILE *out)
{
unsigned char hash[32];
char *ibuf, *obuf;
uint32_t cnum = 0;
size_t ilen = 0, olen = 0;
int end = 0;
ibuf = malloc(BUFFER);
obuf = malloc(BUFFER);
{
sha256_context ctx;
sha256_starts(&ctx);
sha256_update(&ctx, key, strlen(key));
sha256_finish(&ctx, hash);
}
while(end != 2)
{
sc_read(in, ibuf, &ilen, &end);
sc_work(ibuf, &ilen, obuf, &olen, hash, &cnum);
sc_send(out, obuf, &olen);
if ( end == 1 && ilen == 0 && olen == 0 )
end = 2;
}
free(ibuf);
free(obuf);
}
int main(int argc, char *argv[])
{
FILE *in = stdin;
FILE *out = stdout;
if ( argc < 2 || argc > 4 )
{
printf("SCrypt v1.0 by Pascal Gloor\n");
printf("usage: %s <key> [input] [output]\n",argv[0]);
printf("\n");
printf(" key : the key used to crypt/decrypt.\n");
printf(" input : file to read. use '-' for stdin.\n");
printf(" output : file to write. use '-' for stdin.\n");
printf("\n");
printf(" note : if input/output are omited, stdin/stdout\n");
printf(" will be used. this is the default behaviour.\n");
printf("\n");
exit(EXIT_FAILURE);
}
if ( argc >= 3 )
if ( strcmp(argv[2],"-") != 0 )
if ( ( in = fopen(argv[2],"r") ) == NULL )
{
fprintf(stderr,"fopen('%s') error: '%s'\n",argv[2],strerror(errno));
exit(EXIT_FAILURE);
}
if ( argc == 4 )
if ( strcmp(argv[3],"-") != 0 )
if ( ( out = fopen(argv[3],"w") ) == NULL )
{
fprintf(stderr,"fopen('%s') error: '%s'\n",argv[3],strerror(errno));
exit(EXIT_FAILURE);
}
main_loop(argv[1],in,out);
fclose(in);
fclose(out);
return 0;
}