Commit 7c9f0463 authored by gerd's avatar gerd

First release.


git-svn-id: https://godirepo.camlcity.org/svn/lib-cryptgps/trunk@10 b101cce4-44db-0310-b718-db4b2d8d2e05
parent dd3fc1ec
......@@ -11,9 +11,9 @@
# specific rules for this package:
OBJECTS = cryptsystem_64.cmo cryptmodes_64.cmo \
crypt_blowfish.cmo crypt_des.cmo
crypt_blowfish.cmo crypt_des.cmo crypt_3des.cmo
XOBJECTS = cryptsystem_64.cmx cryptmodes_64.cmx \
crypt_blowfish.cmx crypt_des.cmx
crypt_blowfish.cmx crypt_des.cmx crypt_3des.cmx
ARCHIVE = cryptgps.cma
XARCHIVE = cryptgps.cmxa
NAME = cryptgps
......
-------------------------------------------------
cryptgps: some symmetric cryptographic algorithms
-------------------------------------------------
This library implements Blowfish, DES, and Triple-DES.
REQUIREMENTS
The Makefile in this distribution requires that the 'findlib' package
is already installed. 'findlib' is a small tool that simplifies platform-
independent installation.
You can get 'findlib' from:
http://people.darmstadt.netsurf.de/Gerd.Stolpmann/ocaml, or
http://www.npc.de/ocaml/linkdb
(Or you can change the Makefile, if you like.)
COMPILATION & INSTALLATION
Type
make all
to compile a bytecode archive.
make opt
compiles a native archive.
make install
installs the bytecode, and if present, the native archive. The
installation directory is determined by the 'findlib' tool.
make uninstall
removes the installation.
USAGE
The three modules Crypt_blowfish, Crypt_des, and Crypt_3des have all the
following inner structure. The inner module Cryptsystem contains the core
cryptographic routines, you normally need only the key preparation part.
The inner module Cryptmodes implements "modes" of encryption/decryption.
The core algorithms only encrypt/decrypt 64-bit blocks, and a
"cryptographic mode" extends this to strings of arbitrary length.
let k = Crypt_blowfish.Cryptsystem.prepare "abcdefgh"
The function 'prepare' converts the key given as string to an internal
format. Key preparation may be a lengthy procedure.
let ivec = (0,0,0,0)
The initialization vector is a non-secret random number. This means that
you can transmit it with the encrypted data. A good choice is the current
time (0,0,0,0 is bad...). Some modes require not to use the same ivec
more than once for a given key in order to get maximum security.
(The ivec is a quadruple of 16 bit numbers, from MSB to LSB.)
To decrypt the message you must use the same ivec as on encryption.
let ivec', i', s' = Crypt_blowfish.Cryptmodes.encrypt_cfb64 k ivec 0 s
Here, "Cipher-feedback mode" with 64 bits is used. s' is the encrypted
version of s. ivec' and i' are needed for cascaded invocations of cfb64.
Cascading means to encrypt a large string by calling the encryption
function with several smaller substrings. For example, if s = s1 ^ s2,
you can do:
let ivec', i', s1' =
Crypt_blowfish.Cryptmodes.encrypt_cfb64 k ivec 0 s1 in
let ivec'', i'', s2' =
Crypt_blowfish.Cryptmodes.encrypt_cfb64 k ivec' ai' s2
Then is s' = s1' ^ s2'. Cascading is useful with slow I/O devices.
SPEED
Blowfish is three times faster than DES which is three times faster than
Triple-DES. The algorithms have been optimized (my first DES algorithm
needed 170 seconds to encrypt 1 MB, the distributed version only 15
seconds - measured on a 486/133).
A Comparison with ssleay has shown that my library is approximately 8 to
10 times slower (ocamlopt). As Ocaml does not have 32 bit integers, all 32
bit calculations must be performed using two 16 bit numbers; this effect
explains a factor of 2. The integer representation expects a '1' in the
LSB of every integer word which makes Ocaml another bit slower. ssleay
uses static arrays which are often a bit faster; such a feature is not
available in Ocaml.
LICENSE
The program text is copyrighted by Gerd Stolpmann. There may be patents on
the underlying algorithms; note that this may differ in various countries.
So the following refers only to this copyright; there may be other rights
owned by other persons.
You may use, copy, or distribute the cryptgps package either in source
code or binary form (compiled to bytecode or machine instructions). There
is no restriction on commercial use.
You may modify, rearrange, or patch the package, and give it to other
people, but you are expected to include a notice that the modified package
bases on work by Gerd Stolpmann, and that it is modified.
There is no guarantee that the functions in the package work as they are
intended to. In particular, using the package may lead to data loss,
hardware or software defects, or other business interruption. If you use
this package you do it on your own risk.
#! /bin/sh
# (*
exec ocaml "$0"
*) directory "..";;
#load "cryptgps.cma";;
open Crypt_3des;;
open Cryptsystem;;
open Cryptmodes;;
let k = prepare (set_parity "abcdefghijklmnopqrstuvwx");;
let print s =
let l = String.length s in
for i = 0 to l/2-1 do
let j = 2*i in
print_char ' ';
print_int ((Char.code(s.[j]) lsl 8 ) lor (Char.code(s.[j+1])))
done
;;
let (x3,x2,x1,x0) = encrypt_ecb k (0x3132,0x3334,0x3536,0x3738);;
Printf.printf "Result ECB: %d %d %d %d\n" x3 x2 x1 x0;;
let (v, s) = encrypt_cbc k (0,0,0,0) "12345678abcdefgh";;
print_string "Result CBC:";
print s;
print_newline()
;;
let (v, _, s) = encrypt_cfb64 k (0,0,0,0) 0 "12345678abcdefgh";;
print_string "Result CFB-64:";
print s;
print_newline()
;;
let (v, _, s) = crypt_ofb k (0,0,0,0) 0 "12345678abcdefgh";;
print_string "Result OFB:";
print s;
print_newline()
;;
#! /bin/sh
# (*
exec ocaml "$0"
*) directory "..";;
#load "cryptgps.cma";;
open Crypt_des;;
open Cryptsystem;;
open Cryptmodes;;
let k = prepare (set_parity "abcdefgh");;
let print s =
let l = String.length s in
for i = 0 to l/2-1 do
let j = 2*i in
print_char ' ';
print_int ((Char.code(s.[j]) lsl 8 ) lor (Char.code(s.[j+1])))
done
;;
let (x3,x2,x1,x0) = encrypt_ecb k (0x3132,0x3334,0x3536,0x3738);;
Printf.printf "Result ECB: %d %d %d %d\n" x3 x2 x1 x0;;
let (v, s) = encrypt_cbc k (0,0,0,0) "12345678abcdefgh";;
print_string "Result CBC:";
print s;
print_newline()
;;
let (v, _, s) = encrypt_cfb64 k (0,0,0,0) 0 "12345678abcdefgh";;
print_string "Result CFB-64:";
print s;
print_newline()
;;
let (v, _, s) = crypt_ofb k (0,0,0,0) 0 "12345678abcdefgh";;
print_string "Result OFB:";
print s;
print_newline()
;;
#include <stdio.h>
#include "des.h"
void print4(unsigned char *p) {
int x3,x2,x1,x0;
x3 = p[0] << 8 | p[1];
x2 = p[2] << 8 | p[3];
x1 = p[4] << 8 | p[5];
x0 = p[6] << 8 | p[7];
printf(" %d %d %d %d", x3, x2, x1, x0);
}
main () {
des_key_schedule k1,k2,k3;
unsigned char out8[8];
unsigned char out16[16];
unsigned char ivec[8];
int i, num;
des_set_key("abcdefgh",k1);
des_set_key("ijklmnop",k2);
des_set_key("qrstuvwx",k3);
/* ECB TEST */
des_ecb3_encrypt("12345678", out8, k1, k2, k3, 1);
printf("Result ECB:");
print4(out8);
printf("\n");
/* CBC TEST */
for (i=0; i<8; i++) ivec[i] = 0;
des_ede3_cbc_encrypt("12345678abcdefgh", out16, 16, k1, k2, k3, ivec, 1);
printf("Result CBC:");
print4(out16);
print4(out16+8);
printf("\n");
/* CFB-64 TEST */
for (i=0; i<8; i++) ivec[i] = 0;
num = 0;
des_ede3_cfb64_encrypt("12345678abcdefgh", out16, 16, k1, k2, k3, ivec, &num, 1);
printf("Result CFB-64:");
print4(out16);
print4(out16+8);
printf("\n");
/* OFB TEST */
for (i=0; i<8; i++) ivec[i] = 0;
num = 0;
des_ede3_ofb64_encrypt("12345678abcdefgh", out16, 16, k1, k2, k3, ivec, &num);
printf("Result OFB:");
print4(out16);
print4(out16+8);
printf("\n");
}
......@@ -2,5 +2,11 @@ SSLEAY_INCL = /usr/ssl/include
SSLEAY_LIB = /usr/ssl/lib
CC = gcc -I$(SSLEAY_INCL) -L$(SSLEAY_LIB)
all: blowfish des 3des
blowfish: blowfish.c
$(CC) -o blowfish blowfish.c -lcrypto
des: des.c
$(CC) -o des des.c -lcrypto
3des: 3des.c
$(CC) -o 3des 3des.c -lcrypto
#include <stdio.h>
#include "des.h"
void print4(unsigned char *p) {
int x3,x2,x1,x0;
x3 = p[0] << 8 | p[1];
x2 = p[2] << 8 | p[3];
x1 = p[4] << 8 | p[5];
x0 = p[6] << 8 | p[7];
printf(" %d %d %d %d", x3, x2, x1, x0);
}
main () {
des_key_schedule k;
unsigned char out8[8];
unsigned char out16[16];
unsigned char ivec[8];
int i, num;
des_set_key("abcdefgh",k);
/* ECB TEST */
des_ecb_encrypt("12345678", out8, k, 1);
printf("Result ECB:");
print4(out8);
printf("\n");
/* CBC TEST */
for (i=0; i<8; i++) ivec[i] = 0;
des_cbc_encrypt("12345678abcdefgh", out16, 16, k, ivec, 1);
printf("Result CBC:");
print4(out16);
print4(out16+8);
printf("\n");
/* CFB-64 TEST */
for (i=0; i<8; i++) ivec[i] = 0;
num = 0;
des_cfb64_encrypt("12345678abcdefgh", out16, 16, k, ivec, &num, 1);
printf("Result CFB-64:");
print4(out16);
print4(out16+8);
printf("\n");
/* OFB TEST */
for (i=0; i<8; i++) ivec[i] = 0;
num = 0;
des_ofb64_encrypt("12345678abcdefgh", out16, 16, k, ivec, &num);
printf("Result OFB:");
print4(out16);
print4(out16+8);
printf("\n");
}
(* $Id: crypt_3des.ml,v 1.1 1999/06/18 00:23:58 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
let check_parity key =
match String.length key with
8 -> Crypt_des.check_parity key
| 16 -> Crypt_des.check_parity (String.sub key 0 8);
Crypt_des.check_parity (String.sub key 8 8)
| 24 -> Crypt_des.check_parity (String.sub key 0 8);
Crypt_des.check_parity (String.sub key 8 8);
Crypt_des.check_parity (String.sub key 16 8)
| _ -> failwith "Crypt_3des: invalid key length"
;;
let set_parity key =
match String.length key with
8 -> Crypt_des.set_parity key
| 16 -> Crypt_des.set_parity (String.sub key 0 8) ^
Crypt_des.set_parity (String.sub key 8 8)
| 24 -> Crypt_des.set_parity (String.sub key 0 8) ^
Crypt_des.set_parity (String.sub key 8 8) ^
Crypt_des.set_parity (String.sub key 16 8)
| _ -> failwith "Crypt_3des: invalid key length"
;;
module Cryptsystem : Cryptsystem_64.T =
struct
type key =
{ k1 : Crypt_des.Cryptsystem.key;
k2 : Crypt_des.Cryptsystem.key;
k3 : Crypt_des.Cryptsystem.key;
n_keys : int
}
let encrypt_ecb k x =
match k.n_keys with
1 -> Crypt_des.Cryptsystem.encrypt_ecb k.k1 x
| 2 -> let x' = Crypt_des.Cryptsystem.encrypt_ecb k.k1 x in
let x'' = Crypt_des.Cryptsystem.decrypt_ecb k.k2 x' in
Crypt_des.Cryptsystem.encrypt_ecb k.k1 x''
| 3 -> let x' = Crypt_des.Cryptsystem.encrypt_ecb k.k1 x in
let x'' = Crypt_des.Cryptsystem.decrypt_ecb k.k2 x' in
Crypt_des.Cryptsystem.encrypt_ecb k.k3 x''
| _ -> failwith "Crypt_3des: invalid key length"
let decrypt_ecb k x =
match k.n_keys with
1 -> Crypt_des.Cryptsystem.decrypt_ecb k.k1 x
| 2 -> let x' = Crypt_des.Cryptsystem.decrypt_ecb k.k1 x in
let x'' = Crypt_des.Cryptsystem.encrypt_ecb k.k2 x' in
Crypt_des.Cryptsystem.decrypt_ecb k.k1 x''
| 3 -> let x' = Crypt_des.Cryptsystem.decrypt_ecb k.k1 x in
let x'' = Crypt_des.Cryptsystem.encrypt_ecb k.k2 x' in
Crypt_des.Cryptsystem.decrypt_ecb k.k3 x''
| _ -> failwith "Crypt_3des: invalid key length"
let prepare key =
let l_key = String.length key in
match l_key with
8 -> let k = Crypt_des.Cryptsystem.prepare key in
{ k1=k; k2=k; k3=k; n_keys=1 }
| 16 -> let k1 = Crypt_des.Cryptsystem.prepare (String.sub key 0 8) in
let k2 = Crypt_des.Cryptsystem.prepare (String.sub key 8 8) in
{ k1=k1; k2=k2; k3=k1; n_keys=2 }
| 24 -> let k1 = Crypt_des.Cryptsystem.prepare (String.sub key 0 8) in
let k2 = Crypt_des.Cryptsystem.prepare (String.sub key 8 8) in
let k3 = Crypt_des.Cryptsystem.prepare (String.sub key 16 8) in
{ k1=k1; k2=k2; k3=k3; n_keys=3 }
| _ -> failwith "Crypt_3des: invalid key length"
let textkey k =
match k.n_keys with
1 -> Crypt_des.Cryptsystem.textkey k.k1
| 2 -> Crypt_des.Cryptsystem.textkey k.k1 ^
Crypt_des.Cryptsystem.textkey k.k2
| 3 -> Crypt_des.Cryptsystem.textkey k.k1 ^
Crypt_des.Cryptsystem.textkey k.k2 ^
Crypt_des.Cryptsystem.textkey k.k3
| _ -> failwith "Crypt_3des: invalid key length"
let is_weak k =
match k.n_keys with
1 -> Crypt_des.Cryptsystem.is_weak k.k1
| 2 -> Crypt_des.Cryptsystem.is_weak k.k1 or
Crypt_des.Cryptsystem.is_weak k.k2 or
Crypt_des.Cryptsystem.textkey k.k1 =
Crypt_des.Cryptsystem.textkey k.k2
| 3 -> Crypt_des.Cryptsystem.is_weak k.k1 or
Crypt_des.Cryptsystem.is_weak k.k2 or
Crypt_des.Cryptsystem.is_weak k.k3 or
Crypt_des.Cryptsystem.textkey k.k1 =
Crypt_des.Cryptsystem.textkey k.k2 or
Crypt_des.Cryptsystem.textkey k.k1 =
Crypt_des.Cryptsystem.textkey k.k3 or
Crypt_des.Cryptsystem.textkey k.k2 =
Crypt_des.Cryptsystem.textkey k.k3
| _ -> failwith "Crypt_3des: invalid key length"
end
;;
module Cryptmodes = Cryptmodes_64.Make_modes(Cryptsystem)
;;
(* ======================================================================
* History:
*
* $Log: crypt_3des.ml,v $
* Revision 1.1 1999/06/18 00:23:58 gerd
* First release.
*
*
*)
(* $Id: crypt_3des.mli,v 1.1 1999/06/18 00:23:58 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
(* DES, created by the NSA, is a 64 bit block cipher. Triple-DES is a
* variant that applies DES three times to the same input block. More
* precisely, first the block is encrypted with key k1, then decrypted
* with key k2 and then encrypted again with key k3.
* It is best to choose k1,k2,k3 distinct. Sometimes k1=k3.
* This implementation accepts strings with 8, 16, or 24 bytes as keys,
* taking the first 8 bytes as k1, the second as k2, and the third as k3.
* Please note that some bits are used as parity bits, such that the
* effective key length is 56, resp. 112, resp. 168 bits.
*
* Triple-DES is 3 times slower than DES.
*)
module Cryptsystem : Cryptsystem_64.T;;
module Cryptmodes : Cryptmodes_64.T with type key = Cryptsystem.key;;
(* Key management functions:
*
* Although only 56 bits count a DES key is written with 64 bits. The
* extra bits are used for parity checking.
*)
val check_parity : string -> unit
(* Checks that the parity of the key given as string is ok. The string
* must have a length of 8 or 16 or 24 characters.
*)
val set_parity : string -> string
(* Sets the parity bits in the given key and returns a new string. *)
(* - DES has been heavily studied and seems to have a rather good design
* - DES has only 56 bit keys (this means DES should be considered a
* weak algorithm today, but the variant 3DES is still secure)
* - DES has been designed to be implemented in hardware, and software
* implementations are relatively slow
* - DES is an ANSI and (indirectly) an ISO standard.
* - There are very few weak keys.
*)
(* ======================================================================
* History:
*
* $Log: crypt_3des.mli,v $
* Revision 1.1 1999/06/18 00:23:58 gerd
* First release.
*
*)
(* $Id: crypt_des.ml,v 1.8 1999/06/17 21:00:31 gerd Exp $
(* $Id: crypt_des.ml,v 1.9 1999/06/18 00:23:58 gerd Exp $
* ----------------------------------------------------------------------
*
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
(* Note: Bits are numbered from MSB to LSB! *)
......@@ -829,6 +829,9 @@ module Cryptmodes = Cryptmodes_64.Make_modes(Cryptsystem)
* history:
*
* $Log: crypt_des.ml,v $
* Revision 1.9 1999/06/18 00:23:58 gerd
* First release.
*
* Revision 1.8 1999/06/17 21:00:31 gerd
* Some additions have been turned into lor operations (faster).
* The Lazy.force calls in the 'des' functions have been avoided.
......
......@@ -2,7 +2,8 @@ SSLEAY_INCL = /usr/ssl/include
SSLEAY_LIB = /usr/ssl/lib
CC = gcc -I$(SSLEAY_INCL) -L$(SSLEAY_LIB)
all: speed_blowfish_byte speed_blowfish_native speed_blowfish_c
all: speed_blowfish_byte speed_blowfish_native speed_blowfish_c \
speed_des_byte speed_des_native speed_des_c
speed_blowfish_byte: speed_blowfish.ml ../cryptgps.cma
ocamlc -o speed_blowfish_byte -I .. ../cryptgps.cma speed_blowfish.ml
......@@ -12,3 +13,12 @@ speed_blowfish_native: speed_blowfish.ml ../cryptgps.cmxa
speed_blowfish_c: speed_blowfish.c
$(CC) -o speed_blowfish_c speed_blowfish.c -lcrypto
speed_des_byte: speed_des.ml ../cryptgps.cma
ocamlc -o speed_des_byte -I .. ../cryptgps.cma speed_des.ml
speed_des_native: speed_des.ml ../cryptgps.cmxa
ocamlopt -p -o speed_des_native -I .. ../cryptgps.cmxa speed_des.ml
speed_des_c: speed_des.c
$(CC) -o speed_des_c speed_des.c -lcrypto
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include "des.h"
main () {
des_key_schedule k;
unsigned char in[1024*1024];
unsigned char out[1024*1024];
unsigned char ivec[8];
int i;
struct timeval tv;
double t1,t2;
des_set_key("abcdefgh",k);
/* CBC TEST */
for (i=0; i<8; i++) ivec[i] = 0;
for (i=0; i<1024*1024; i++) in[i] = ' ';
gettimeofday(&tv, NULL);
t1 = tv.tv_sec + tv.tv_usec * 1E-6;
des_cbc_encrypt(in, out, 1024*1024, k, ivec, 1);
gettimeofday(&tv, NULL);
t2 = tv.tv_sec + tv.tv_usec * 1E-6;
printf("%f\n", t2-t1);
}
open Crypt_des;;
open Cryptsystem;;
open Cryptmodes;;
let k = prepare (set_parity "abcdefgh");;
let s = String.make (1024*1024) ' ';;
let x0 = Sys.time() in
ignore(encrypt_cbc k (0,0,0,0) s);
print_float (Sys.time() -. x0);
print_newline()
;;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment