/***************************************************************************
                          hbcirsakey.h  -  description
                             -------------------
    begin                : Sun Jul 1 2001
    copyright            : (C) 2001 by fabian kaiser
    email                : fabian.kaiser@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library 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     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/

/*
 */


#ifndef HBCIRSAKEY_H
#define HBCIRSAKEY_H

#include <string>
#include <openhbci/dllimport.h>
#include <openhbci/cryptkey.h>

#define DEFAULT_KEY_LENGTH 768
#define DEFAULT_EXPONENT 65537
using namespace std;

/* forward declaration to skip including "openssl/rsa.h" */
typedef struct rsa_st RSA;

namespace HBCI {

/**
 * @short Performs encryption and decryption with rsa.
 *
 * Also, padding method ISO-9796 is available.
 * @author fabian kaiser
 */
class DLLIMPORT RSAKey : public CryptKey  {
public:

    /**
     * @author Martin Preuss<openhbci@aquamaniac.de>
     */
    struct DLLIMPORT keyData {
        bool isPublic;
        bool isCrypt;
        string owner;
        int number;
        int version;
        string modulus;
        int exponent;
        string n;
        string p;
        string q;
        string d;
        string dmp1;
        string dmq1;
        string iqmp;
    };

    RSAKey(bool publicKey = false);

    /**
     * Reads the key from a keyData struct.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     */
    RSAKey(keyData *kd);

    ~RSAKey();


    /**
     * create a pair of rsa-keys, one public, one private
     */
    DLLIMPORT static void generateKeyPair(unsigned int keyLength,
                                          RSAKey **privKey,
                                          RSAKey **pubKey);

    string toString();

    /**
     *
     * @throws Message*
     */
    void loadDataFromString(const string &keyData);

    /**
     * @author Martin Preuss<openhbci@aquamaniac.de>
     */
    bool getKeyData(keyData *kd);

    /**
     * is this the public key?
     */
    bool isPublicKey() const { return isPublic;};

    /**
     * is this a key for encrypting (or for signing)
     */
    bool isCryptoKey() const { return isCryptKey;};

    /**
     * verify the signature of given data
     * (this key has to be the public one)
     */
    bool verify(const string &signature);

    /**
     * sign data
     * (this key should be the private one, otherways it would be pretty senseless...)
     */
    bool sign();

    /**
     * encrypt data
     */
    bool encrypt();

    /**
     * decrypt data
     */
    bool decrypt();

    /**
     * return the version-number of the key
     */
    int number() const { return _number;};

	/**
	 * Set a new version-number for this key.
	 */
	void setNumber(int newNumber) { _number = newNumber; };

    /**
     * return the sub-version-number of the key
     */
    int version() const { return _version;};

	/**
	 * Set a new sub-version-number for this key
	 */
	void setVersion(int newVersion) { _version = newVersion; };

    /**
     * return the userid that belongs to this key (intitute-key: the 
	 * unique id for this key)
     */
    const string &userId() const { return myUserId;};

    /**
     * set owner of this key
     */
    void setUserId(const string &id) {myUserId=id;};

    /**
     * return the binary representation of the modulus if this is a public key (otherways result is undefined)
     */
    string getModulusData() const { return modulus;};

    /**
     * return the binary representation of the exp. (should by 3 byte long with exp = 65537)
     */
    string getExpData() const;

    /**
     * return the ini-letter-modulus that is needed to print the ini-letter
     */
    string getIniLetterModulus() const;

    /**
     * return the ini-letter-exponent that is needed to print the ini-letter
     */
    string getIniLetterExponent() const;

    /**
     * return the ini-letter-hash that is needed to print the ini-letter
     */
    string getIniLetterHash() const;


    /**
     * should this be a signature-key
     */
    void setToSignKey(bool signKey) { isCryptKey = ! (signKey);};
private:
    void fillRSAStruct(RSA *rsaStruct);
    unsigned char pi(unsigned char input);
    string paddWithISO9796(string source);
    string ripe(string source) const;

    bool isPublic;
    bool isCryptKey;
    int _number;
    int _version;
    string myUserId;

    string modulus;
    int exponent;
    string n;
    string p;
    string q;
    string d;
    string dmp1;
    string dmq1;
    string iqmp;

    DLLIMPORT static unsigned char lookUp[2][16];
    /** Used by loadDataFromString. */
    static string loadDataNext(const string &keystring,
			       unsigned int &tpos);
};

} /* namespace HBCI */
#endif
