    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Coded.Encryption.RSA
    -- Copyright   :  (c) David J. Sankel 2003, Dominic Steinitz 2003
    -- License     :  GPL (see the file ReadMe.tex)
    --
    -- Maintainer  :  dominic.steinitz@blueyonder.co.uk
    -- Stability   :  experimental
    -- Portability :  non-portable
    --
    -- A modified version of the RSA module supplied by David J. Sankel
    -- (<http://www.electronconsulting.com/rsa-haskell>).
    --
    -- As the original code is GPL, this has to be.
    -- This code is free software; you can redistribute it and\/or modify
    -- it under the terms of the GNU General Public License as published by
    -- the Free Software Foundation; either version 2 of the License, or
    -- (at your option) any later version.
    --
    -- This code is distributed in the hope that it will be useful,
    -- but WITHOUT ANY WARRANTY; without even the implied warranty of
    -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    -- GNU General Public License for more details.
    --
    -- You should have received a copy of the GNU General Public License
    -- along with this code; if not, write to the Free Software
    -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111\-1307  USA
    -----------------------------------------------------------------------------

    module Codec.Encryption.RSA(
      -- * Function Types
      encrypt,
      decrypt
      )where

    import Codec.Utils
    import Codec.Encryption.RSA.NumberTheory

    rsaep :: (Integer , Integer) -> Integer -> Integer
    rsaep (n,e) m
       | m < 0 || m > n-1 =
            error "Codec.Encryption.RSA.rsaep: message too long"
       | otherwise =
            expmod m e n

    -- | Take the modulus of the RSA key and the public exponent expressed
    -- as lists of octets and the plaintext also expressed as a list of
    -- octets and return the ciphertext as a list of octets. Of course,
    -- these are all large integers but using lists of octets makes
    -- everything easier. See
    -- <http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html> for more
    -- details.

    encrypt :: ([Octet],[Octet]) -> [Octet] -> [Octet]
    encrypt (n,e) m =
       i2osp (length n) $
        rsaep (fromOctets 256 n, fromOctets 256 e) (fromOctets 256 m)

    rsadp :: (Integer , Integer) -> Integer -> Integer
    rsadp (n,d) c
       | c < 0 || c > n-1 =
            error "Codec.Encryption.RSA.rsadp: decryption error"
       | otherwise =
            expmod c d n

    -- | Take the modulus of the RSA key and the private exponent expressed
    -- as lists of octets and the ciphertext also expressed as a list of
    -- octets and return the plaintext as a list of octets.

    decrypt :: ([Octet],[Octet]) -> [Octet] -> [Octet]
    decrypt (n,e) m
       | lc > lm =
            error "Codec.Encryption.RSA.rsadp: decryption error"
       | otherwise =
            i2osp (length n) $
            rsadp (fromOctets 256 n, fromOctets 256 e) (fromOctets 256 m)
       where
          lc = length $ dropWhile (==0x00) m
          lm = length $ dropWhile (==0x00) n