Commit 02333b5b authored by gerd's avatar gerd

Initial revision.


git-svn-id: https://godirepo.camlcity.org/svn/lib-cryptgps/trunk@1 b101cce4-44db-0310-b718-db4b2d8d2e05
parents
# make all: make bytecode archive
# make opt: make native archive
# make install: install bytecode archive, and if present, native archive
# make uninstall: uninstall package
# make clean: remove intermediate files
# make distclean: remove any superflous files
# make release: cleanup, create archive, tag CVS module
# (for developers)
#----------------------------------------------------------------------
# specific rules for this package:
OBJECTS = cryptsystem_64.cmo cryptmodes_64.cmo crypt_blowfish.cmo
XOBJECTS = cryptsystem_64.cmx cryptmodes_64.cmx crypt_blowfish.cmx
ARCHIVE = cryptgps.cma
XARCHIVE = cryptgps.cmxa
NAME = cryptgps
REQUIRES =
all: $(ARCHIVE)
opt: $(XARCHIVE)
$(ARCHIVE): $(OBJECTS)
$(OCAMLC) -a -o $(ARCHIVE) $(OBJECTS)
$(XARCHIVE): $(XOBJECTS)
$(OCAMLOPT) -a -o $(XARCHIVE) $(XOBJECTS)
#----------------------------------------------------------------------
# general rules:
OPTIONS =
OCAMLC = ocamlc $(OPTIONS) $(ROPTIONS)
OCAMLOPT = ocamlopt $(OPTIONS) $(ROPTIONS)
OCAMLDEP = ocamldep $(OPTIONS)
OCAMLFIND = ocamlfind
depend: *.ml *.mli
$(OCAMLDEP) *.ml *.mli >depend
depend.pkg: Makefile
$(OCAMLFIND) use -p ROPTIONS= $(REQUIRES) >depend.pkg
.PHONY: install
install: all
{ test ! -f $(XARCHIVE) || extra="*.cmxa *.a"; }; \
$(OCAMLFIND) install $(NAME) *.mli *.cmi *.cma RELEASE $$extra
.PHONY: uninstall
uninstall:
$(OCAMLFIND) remove $(NAME)
.PHONY: clean
clean:
rm -f *.cmi *.cmo *.cma *.cmx *.o *.a *.cmxa
.PHONY: distclean
distclean: clean
rm -f *~
.PHONY: dist
dist:
r=`head -1 RELEASE`; cd ..; gtar czf $(NAME)-$$r.tar.gz $(NAME)
.PHONY: tag-release
tag-release:
r=`head -1 RELEASE | sed -e s/\\\./-/g`; cd ..; cvs tag -F $(NAME)-$$r $(NAME)
.PHONY: release
release: distclean
$(MAKE) tag-release
$(MAKE) dist
.ml.cmx:
$(OCAMLOPT) -inline 10000 -c $<
.ml.cmo:
$(OCAMLC) -c $<
.mli.cmi:
$(OCAMLC) -c $<
.SUFFIXES: .cmo .cmi .cmx .ml .mli
include depend
include depend.pkg
\ No newline at end of file
#! /bin/sh
# (*
exec ocaml "$0"
*) directory "..";;
#load "cryptgps.cma";;
open Crypt_blowfish;;
open Cryptsystem;;
open Cryptmodes;;
let k = prepare "abcdefghijklmnop";;
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()
;;
SSLEAY_INCL = /usr/ssl/include
SSLEAY_LIB = /usr/ssl/lib
CC = gcc -I$(SSLEAY_INCL) -L$(SSLEAY_LIB)
blowfish: blowfish.c
$(CC) -o blowfish blowfish.c -lcrypto
#include <stdio.h>
#include "blowfish.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 () {
BF_KEY k;
unsigned char out8[8];
unsigned char out16[16];
unsigned char ivec[8];
int i, num;
BF_set_key(&k, 16, "abcdefghijklmnop");
/* ECB TEST */
BF_ecb_encrypt("12345678", out8, &k, 1);
printf("Result ECB:");
print4(out8);
printf("\n");
/* CBC TEST */
for (i=0; i<8; i++) ivec[i] = 0;
BF_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;
BF_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;
BF_ofb64_encrypt("12345678abcdefgh", out16, 16, &k, ivec, &num);
printf("Result OFB:");
print4(out16);
print4(out16+8);
printf("\n");
}
This diff is collapsed.
(* $Id: crypt_blowfish.mli,v 1.1 1999/06/04 20:42:01 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
(* "Blowfish", created by Bruce Schneier, is a 64 bit block cipher,
* so the following applies:
*)
module Cryptsystem : Cryptsystem_64.T;;
module Cryptmodes : Cryptmodes_64.T with type key = Cryptsystem.key;;
(* - Blowfish is one of the fastest ciphers.
* - Blowfish supports keys from 8 bits to 448 bits. With longer keys
* the algorithm does not slow down.
* - There are weak keys. It is possible to recover some initialization
* data for weak keys, but no way to exploit this knowlege has been
* reported.
* - Blowfish is public domain, i.e. free from patents.
*)
(* ======================================================================
* History:
*
* $Log: crypt_blowfish.mli,v $
* Revision 1.1 1999/06/04 20:42:01 gerd
* Initial revision.
*
*
*)
(* $Id: cryptmodes_64.ml,v 1.1 1999/06/04 20:42:01 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
module type T =
sig
type key
val encrypt_cbc :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
val decrypt_cbc :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
val encrypt_cfb8 :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
val decrypt_cfb8 :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
val encrypt_cfb64 :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
val decrypt_cfb64 :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
val crypt_ofb :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
end
;;
module Make_modes (M : Cryptsystem_64.T) =
struct
type key = M.key
let encrypt_cbc k iv data =
let l = String.length data in
if l mod 8 <> 0 then failwith "encrypt_cbc";
let n = l / 8 in
let data' = String.create l in
let v = ref iv in
for i = 0 to n-1 do
let j = 8*i in
let x3 = (Char.code(data.[j]) lsl 8) lor (Char.code(data.[j+1])) in
let x2 = (Char.code(data.[j+2]) lsl 8) lor (Char.code(data.[j+3])) in
let x1 = (Char.code(data.[j+4]) lsl 8) lor (Char.code(data.[j+5])) in
let x0 = (Char.code(data.[j+6]) lsl 8) lor (Char.code(data.[j+7])) in
let (v3,v2,v1,v0) = !v in
v := M.encrypt_ecb k (v3 lxor x3, v2 lxor x2, v1 lxor x1, v0 lxor x0);
let (v3',v2',v1',v0') = !v in
data'.[j] <- Char.chr(v3' lsr 8);
data'.[j+1] <- Char.chr(v3' land 0xff);
data'.[j+2] <- Char.chr(v2' lsr 8);
data'.[j+3] <- Char.chr(v2' land 0xff);
data'.[j+4] <- Char.chr(v1' lsr 8);
data'.[j+5] <- Char.chr(v1' land 0xff);
data'.[j+6] <- Char.chr(v0' lsr 8);
data'.[j+7] <- Char.chr(v0' land 0xff);
done;
!v, data'
let decrypt_cbc k iv data =
let l = String.length data in
if l mod 8 <> 0 then failwith "decrypt_cbc";
let n = l / 8 in
let data' = String.create l in
let v = ref iv in
for i = 0 to n-1 do
let j = 8*i in
let x3 = (Char.code(data.[j]) lsl 8) lor (Char.code(data.[j+1])) in
let x2 = (Char.code(data.[j+2]) lsl 8) lor (Char.code(data.[j+3])) in
let x1 = (Char.code(data.[j+4]) lsl 8) lor (Char.code(data.[j+5])) in
let x0 = (Char.code(data.[j+6]) lsl 8) lor (Char.code(data.[j+7])) in
let (y3,y2,y1,y0) = M.decrypt_ecb k (x3,x2,x1,x0) in
let (v3,v2,v1,v0) = !v in
let z3 = y3 lxor v3 in
let z2 = y2 lxor v2 in
let z1 = y1 lxor v1 in
let z0 = y0 lxor v0 in
data'.[j] <- Char.chr(z3 lsr 8);
data'.[j+1] <- Char.chr(z3 land 0xff);
data'.[j+2] <- Char.chr(z2 lsr 8);
data'.[j+3] <- Char.chr(z2 land 0xff);
data'.[j+4] <- Char.chr(z1 lsr 8);
data'.[j+5] <- Char.chr(z1 land 0xff);
data'.[j+6] <- Char.chr(z0 lsr 8);
data'.[j+7] <- Char.chr(z0 land 0xff);
v := (x3,x2,x1,x0);
done;
!v, data'
let encrypt_cfb8 k iv data =
let l = String.length data in
let data' = String.create l in
let sr = ref iv in (* shift register *)
for i = 0 to l-1 do
let (v,_,_,_) = M.encrypt_ecb k !sr in
let c = Char.code(data.[i]) lxor (v lsr 8) in
data'.[i] <- Char.chr c;
let (sr3, sr2, sr1, sr0) = !sr in
sr := (((sr3 lsl 8) land 0xff00) lor (sr2 lsr 8),
((sr2 lsl 8) land 0xff00) lor (sr1 lsr 8),
((sr1 lsl 8) land 0xff00) lor (sr0 lsr 8),
((sr0 lsl 8) land 0xff00) lor c);
done;
!sr, data'
let decrypt_cfb8 k iv data =
let l = String.length data in
let data' = String.create l in
let sr = ref iv in (* shift register *)
for i = 0 to l-1 do
let (v,_,_,_) = M.encrypt_ecb k !sr in (* sic! *)
let c = Char.code(data.[i]) in
let p = c lxor (v lsr 8) in
data'.[i] <- Char.chr p;
let (sr3, sr2, sr1, sr0) = !sr in
sr := (((sr3 lsl 8) land 0xff00) lor (sr2 lsr 8),
((sr2 lsl 8) land 0xff00) lor (sr1 lsr 8),
((sr1 lsl 8) land 0xff00) lor (sr0 lsr 8),
((sr0 lsl 8) land 0xff00) lor c);
done;
!sr, data'
let array_of_quadrupel (n3,n2,n1,n0) =
[| n3 lsr 8;
n3 land 0xff;
n2 lsr 8;
n2 land 0xff;
n1 lsr 8;
n1 land 0xff;
n0 lsr 8;
n0 land 0xff |]
let quadrupel_of_array a =
((a.(0) lsl 8) lor a.(1),
(a.(2) lsl 8) lor a.(3),
(a.(4) lsl 8) lor a.(5),
(a.(6) lsl 8) lor a.(7))
let encrypt_cfb64 k iv j data =
if j < 0 or j > 7 then failwith "encrypt_cfb64";
let l = String.length data in
let data' = String.create l in
let sr_a = ref (array_of_quadrupel iv) in
let jc = ref j in
for i = 0 to l-1 do
if !jc = 0 then
sr_a := array_of_quadrupel
(M.encrypt_ecb k (quadrupel_of_array !sr_a));
let sr_jc = (!sr_a).(!jc) in
let c = Char.code(data.[i]) lxor sr_jc in
data'.[i] <- Char.chr c;
(!sr_a).(!jc) <- c;
jc := (!jc + 1) mod 8;
done;
let sr = quadrupel_of_array !sr_a in
sr, !jc, data'
let decrypt_cfb64 k iv j data =
if j < 0 or j > 7 then failwith "decrypt_cfb64";
let l = String.length data in
let data' = String.create l in
let sr_a = ref (array_of_quadrupel iv) in
let jc = ref j in
for i = 0 to l-1 do
if !jc = 0 then
sr_a := array_of_quadrupel
(M.encrypt_ecb k (quadrupel_of_array !sr_a));
let sr_jc = (!sr_a).(!jc) in
let c = Char.code(data.[i]) in
data'.[i] <- Char.chr (c lxor sr_jc);
(!sr_a).(!jc) <- c;
jc := (!jc + 1) mod 8;
done;
let sr = quadrupel_of_array !sr_a in
sr, !jc, data'
let crypt_ofb k iv j data =
if j < 0 or j > 7 then failwith "crypt_ofb";
let l = String.length data in
let data' = String.create l in
let sr_a = ref (array_of_quadrupel iv) in
let jc = ref j in
for i = 0 to l-1 do
if !jc = 0 then
sr_a := array_of_quadrupel
(M.encrypt_ecb k (quadrupel_of_array !sr_a));
let sr_jc = (!sr_a).(!jc) in
let c = Char.code(data.[i]) lxor sr_jc in
data'.[i] <- Char.chr c;
jc := (!jc + 1) mod 8;
done;
let sr = quadrupel_of_array !sr_a in
sr, !jc, data'
end
;;
(* ======================================================================
* History:
*
* $Log: cryptmodes_64.ml,v $
* Revision 1.1 1999/06/04 20:42:01 gerd
* Initial revision.
*
*
*)
(* $Id: cryptmodes_64.mli,v 1.1 1999/06/04 20:42:01 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
(* OVERVIEW:
*
* A block cipher encrypts or decrypts a fixed amount of bits on every
* invocation. Here, we assume that the underlying cipher handles 64 bit
* blocks as elementary units.
* If you have a message which is a multiple of 64 bits, you could encrypt
* every block independently. IT IS STRONGLY RECOMMENDED NOT TO USE THIS
* SIMPLE APPROACH. This method, often called ECB ("electronic code book"),
* is vulnerable by plaintext attacks, even if a strong cipher is used.
* This module implements the following, much better alternatives.
*
* ---------------------
* CIPHER BLOCK CHAINING
* ---------------------
*
* USAGE, LIMITATIONS:
*
* - buffer size: the buffer to be en/decrypted must be a multiple of 64 bits.
* - initialization vector: the ivec used for encryption must be same as the
* ivec for decryption. The ivec is not secret, it can be transmitted along
* with the ciphertext. It is recommended to use the timestamp as ivec,
* or some random bits.
*
* SECURITY:
*
* - good:
* plaintext patterns (i.e. text structure in the plaintext) is hidden in
* the ciphertext
* - bad: some manipulations in the ciphertext at the end of the message
* are possible. To avoid this, compute an MD5 hash of the message, and
* PREPEND the hash value to the message.
*
* FAULT-TOLERANCE:
*
* - a bit error in the ciphertext affects the corresponding plaintext and
* the following block
* - no recovery from synchronisation errors possible (missing or extra bits)
*
* --------------------
* CIPHER-FEEDBACK MODE
* --------------------
*
* USAGE, LIMITATIONS:
*
* - buffer size: no restrictions
* - initialization vector: the ivec used for encryption must be same as the
* ivec for decryption. The ivec is not secret, it can be transmitted along
* with the ciphertext. A different ivec must be used for every transmitted
* message, e.g. MD5(timestamp + serial number).
*
* SECURITY:
*
* - good:
* plaintext patterns (i.e. text structure in the plaintext) is hidden in
* the ciphertext
* - bad: some manipulations in the ciphertext at the end of the message
* are possible. To avoid this, compute an MD5 hash of the message, and
* PREPEND the hash value to the message.
*
* FAULT TOLERANCE:
*
* - a bit error in the ciphertext affects the corresponding plaintext and
* the following block
* - n-bit CFB can recover from missing n or extra n bits.
*
* --------------------
* OUTPUT-FEEDBACK MODE
* --------------------
*
* USAGE, LIMITATIONS:
*
* - buffer size: no restrictions
* - initialization vector: the ivec used for encryption must be same as the
* ivec for decryption. The ivec is not secret, it can be transmitted along
* with the ciphertext. A different ivec must be used for every transmitted
* message, e.g. MD5(timestamp + serial number).
*
* SECURITY:
*
* - good:
* plaintext patterns (i.e. text structure in the plaintext) is hidden in
* the ciphertext
* - bad:
* manipulation of bits in the ciphertext directly affects the corresponding
* bits in the plaintext
*
* FAULT TOLERANCE:
*
* - a bit error in the ciphertext affects only corresponding plaintext bit
* - n-bit CFB cannot recover from missing or extra bits.
*
* --------------
* RECOMMENDATION
* --------------
*
* - If the encrypted messages are transmitted on a serial line, use CFB-8.
* This is the only mode which can recover from synchronization errors on
* byte level.
* - If your message is a multiple of 64 bits, use CBC. If possible, pad
* the message to fill up to the next 64 bit multiple, and send the length
* of the message, too.
* - Otherwise, use CFB-64.
*)
module type T =
sig
type key
(* CIPHER BLOCK CHAINING MODE *)
val encrypt_cbc :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
(* Encrypts the string whose length MUST be a multiple of 8 bytes
* with the given key and initialization vector, resulting in the
* output vector (for the next CBC cascade) and the encrypted string.
* The size of the string remains unchanged when it is encrypted.
*)
val decrypt_cbc :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
(* Decrypts the string whose length MUST be a multiple of 8 bytes
* with the given key and initialization vector, resulting in the
* output vector (for the next CBC cascade) and the decrypted string.
*)
(* 8 BIT CIPHER-FEEDBACK MODE *)
(* This is 8 times slower than CBC *)
val encrypt_cfb8 :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
(* Encrypts the string (with arbitraty length) with the given key
* and initialization vector, resulting in the output vector (for
* the next CFB cascade) and the encrypted string (of the same
* length).
*)
val decrypt_cfb8 :
key -> (int * int * int * int) -> string ->
((int * int * int * int) * string)
(* Decrypts the string (with arbitraty length) with the given key
* and initialization vector, resulting in the output vector (for
* the next CFB cascade) and the decrypted string (of the same
* length).
*)
(* 64 BIT CIPHER-FEEDBACK MODE *)
val encrypt_cfb64 :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
(* Encrypts the string (with arbitraty length) with the given key
* and initialization vector, resulting in the output vector (for
* the next CFB cascade) and the encrypted string (of the same
* length).
* Compared with cfb8, there is an additional int that it passed
* to and from this function. It is always in the range 0..7 and
* indicates which byte of the 64 bit block comes next. In doubt,
* pass a 0 as this int.
*)
val decrypt_cfb64 :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
(* Decrypts the string (with arbitraty length) with the given key
* and initialization vector, resulting in the output vector (for
* the next CFB cascade) and the decrypted string (of the same
* length).
*)
(* OUTPUT-FEEDBACK MODE (64 bit) *)
val crypt_ofb :
key -> (int * int * int * int) -> int -> string ->
((int * int * int * int) * int * string)
(* Encrypts/Decrypts the string
* with the given key and initialization vector, resulting in the
* output vector (for the next OFB cascade) and the encrypted string.
* The size of the string remains unchanged when it is encrypted.
*)
end
;;
(* Derives the other modes from the basic ECB mode. *)
module Make_modes (M : Cryptsystem_64.T) : T with type key = M.key
;;
(* ======================================================================
* History:
*
* $Log: cryptmodes_64.mli,v $
* Revision 1.1 1999/06/04 20:42:01 gerd
* Initial revision.
*
*
*)
(* $Id: cryptsystem_64.ml,v 1.1 1999/06/04 20:42:01 gerd Exp $
* ----------------------------------------------------------------------
* This module is part of the cryptgps package by Gerd Stolpmann.
*)
(* The module type of a cryptsystem using 64 bit block ciphers. *)
module type T =
sig
type key
(* This is the internal, often preprocessed representation of keys. *)
val encrypt_ecb :
key -> (int * int * int * int) -> (int * int * int * int)
(* This is the ECB mode of the encryption function. The four ints
* are numbers from 0 to 65535, and given from MSB to LSB.