This library collects together existing Haskell cryptographic functions and augments them so that they:
· Have common type signatures.
· Can be used with the standard mode and padding algorithms (in the case of block mode ciphers).
This release contains:
· DES
· Blowfish
· AES
· Cipher Block Chaining (CBC) mode
· PKCS5 and nulls padding
· SHA-1
· MD5
· RSA
· OAEP
· ASN.1
· PKCS#8
The code has been tested on GHC 6.2.1 and Hugs November 2003 and should work on all higher versions. It does not work with NHC.
Download http://www.haskell.org/crypto/downloads/crypto-1.2.2.tar.
tar -xvf crypto-1.2.2.tar
make depend
make
make install
make doc
You will need to be root to make install. You should then be able to compile and run the test programs from anywhere:
ghc -o Test Test.hs -package crypto
./Test
Testing DES...
Passed
Testing Blowfish...
Passed
Testing AES...
Passed
ghc -o RSATest RSATest.hs -package crypto
./RSATest
Testing product of primes...
Passed
Testing exponent1...
Passed
Testing encoding...
Passed
Testing encryption...
Passed
ghc -o Pkcs8Test Pkcs8Test.hs -package crypto
./Pkcs8Test
[78,111,119,32,105,115,32,116,104,101,32,116,105,109,101,46,46,46,10]
All examples assume that you have imported the correct modules, for example:
module Main(main) where
import Codec.Encryption.Utils
import Codec.Encryption.LargeKey
import Codec.Encryption.Blowfish as Blowfish
import Codec.Encryption.Modes
import Codec.Encryption.Padding
import Codec.Encryption.DES as DES
import Codec.Encryption.AES as AES
import Data.Word
import Data.Bits
import Numeric
import Char
See
http://www.schneier.com/code/vectors.txt
for more test vectors.
d = 0xFEDCBA9876543210 :: Word64
k = 0xF0 :: Word8
e = Blowfish.encrypt k d
k2 = 0xF0E1 :: Word16
e2 = Blowfish.encrypt k2 d
k8 = 0xF0E1D2C3B4A59687 :: Word64
e8 = Blowfish.encrypt k8 d
k16= 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128
e16 = Blowfish.encrypt k16 d
key16 = 0x0123456789ABCDEFF0E1D2C3B4A59687 :: Word128
iv8 = 0xFEDCBA9876543210 :: Word64
data29 = "7654321 Now is the time for \NUL"
e29 =
cbc Blowfish.encrypt iv8 key16 $ padNulls $
map (fromIntegral . ord) data29
Taken from http://www.itl.nist.gov/fipspubs/fip81.htm.
key = 0x0123456789abcdef
iv = 0x1234567890abcdef
plainText = "Now is the time for all "
cipherText =
cbc DES.encrypt iv key $ pkcs5 $ map (fromIntegral . ord) plaintext
Taken from http://www.cs.ucsd.edu/~fritz/rijndael_test.html.
ad = 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128
ak24 = 0xF0E1D2C3B4A5968778695A4B3C2D1E0FF0E1D2C3B4A59687 :: Word192
ae24' = AES.encrypt ak24 ad
ae24 = 0x07d806bb62ebb4399354594ea6586ec6
aes2 = ae24 == ae24'
Taken from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf.
aes4key32 =
0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 :: Word256
aes4iv16 = 0x000102030405060708090a0b0c0d0e0f :: Word128
aes4plaintext =
[0x6bc1bee22e409f96e93d7e117393172a,
0xae2d8a571e03ac9c9eb76fac45af8e51,
0x30c81c46a35ce411e5fbc1191a0a52ef,
0xf69f2445df4f9b17ad2b417be66c3710] :: [Word128]
aes4ciphertext' =
cbc AES.encrypt aes4iv16 aes4key32 $
pkcs5 $
concat $
map toOctets aes3plaintext
aes4ciphertext =
[0xf58c4c04d6e5f1ba779eabfb5f7bfbd6,
0x9cfc4e967edb808d679f777bc6702c7d,
0x39f23369a9d9bacfa530e26304231461,
0xb2eb05e2c39be9fcda6c19078c6a9d1b] :: [Word128]
aescbc5 = aes4ciphertext == take 4 aes4ciphertext'
Generate a private key using openssl (http://www.openssl.org/)
openssl genrsa -out private.pem
Convert it to PKCS8 (you can look at it with Peter
Gutmann's ASN.1 object dump program http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c
if required). N.B., in this example, the private key is unencrypted. Storing
private keys in clear is not good security practice. The current implementation
does not support encrypted private keys but this should be straightforward to
add.
openssl pkcs8 -topk8 -inform PEM -outform DER -in private.pem -nocrypt -out private.der
Generate a public key from the private key.
openssl rsa -in private.pem -pubout -out public.pem
Create a plaintext file.
echo "Now is the time..." > plaintext
Encrypt it, not forgetting to specify OAEP encoding.
openssl rsautl -encrypt -pubin -inkey public.pem -in plaintext -out ciphertext -oaep
Decrypt it in your Haskell program.
module Main(main) where
import IO
import Char
import Control.Monad.State
import Codec.ASN1.ASN1 as A
import Codec.Encryption.Utils
import Codec.Encryption.PKCS8
import Codec.Encryption.SHA1
import Codec.Encryption.MGF
import Codec.Encryption.EMEOAEP as E
import Codec.Encryption.RSA
plaintext n d x =
E.decode mgf hash [] $
decrypt (n,d) $
map (fromIntegral . ord) x
main =
do ifh <- openFile "private.der" ReadMode
(x,y) <- A.decode ifh
let z = fromASN NoTag y
x <- readFile "ciphertext"
putStrLn $ show $ plaintext (toOctets $ modulus $ privateKey z)
(toOctets $ privateExponent $ privateKey z) x
In no particular order:
· Read and generate PKCS12 private keys so that it is easy to inter-work with other RSA implementations.
· X.509 certificates.
· Incorporate other symmetric key algorithms already coded in Haskell.
· Performance analysis as Blowfish ought to run more quickly than DES.
· Other modes / padding schemes.
· XML encryption and digital signatures.
http://www.electronconsulting.com/rsa-haskell
http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh
All questions, comments, bug reports, flames, requests for updates / changes and suggestions should be directed to .
The modules in the library come from different authors and have been released under different licences. See the source code of each module for the license under which it has been released.
Cryptography is a notoriously easy area in which to make mistakes, not necessarily with the algorithms but with how they are implemented (for example not protecting keys, using weak keys and so on). For a readable account of some of the pitfalls, see Ross Anderson’s book.
THIS
SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Doug
Hoyte (HardCore SoftWare)
Ian
Lynagh (http://web.comlab.ox.ac.uk/oucl/work/ian.lynagh)
David
Sankel (http://www.electronconsulting.com/whois.html)
Ross
Paterson (http://www.soi.city.ac.uk/~ross)
Lukasz Anforowicz
======================================================================
Copyright © 2003 - 2004 Dominic Steinitz. Last updated on 2nd
October 04.
======================================================================