Package org.kapott.hbci.passport

Source Code of org.kapott.hbci.passport.AbstractRDHSWPassport

/*  $Id: AbstractRDHSWPassport.java,v 1.1 2011/05/04 22:37:43 willuhn Exp $

    This file is part of HBCI4Java
    Copyright (C) 2001-2008  Stefan Palme

    HBCI4Java 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.

    HBCI4Java 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 program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package org.kapott.hbci.passport;

import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.kapott.cryptalgs.RSAPrivateCrtKey2;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIKey;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.manager.HBCIUtilsInternal;

public abstract class AbstractRDHSWPassport
  extends AbstractRDHPassport
{
    protected HBCIKey[][] keys;

    protected AbstractRDHSWPassport(Object init)
    {
      super(init);
     
        keys=new HBCIKey[3][];
        for (int i=0;i<3;i++) {
            keys[i]=new HBCIKey[2];
            for (int j=0;j<2;j++) {
                keys[i][j]=null;
            }
        }
    }
   
    public boolean hasInstSigKey()
    {
        return getInstSigKey()!=null;
    }
   
    public boolean hasInstEncKey()
    {
        return getInstEncKey()!=null;
    }
   
    public boolean hasMySigKey()
    {
        return getMyPublicSigKey()!=null;
    }
   
    public boolean hasMyEncKey()
    {
        return getMyPublicEncKey()!=null;
    }
   
    public HBCIKey getKey(int i,int j)
    {
        return keys[i][j];
    }
   
    public void setInstSigKey(HBCIKey key)
    {
        setKey(0,0,key);
    }

    public void setInstEncKey(HBCIKey key)
    {
        setKey(0,1,key);
    }

    public void setMySigKey(HBCIKey key)
    {
        setKey(1,0,key);
        setKey(1,1,key);
    }

    public void setMyEncKey(HBCIKey key)
    {
        setKey(2,0,key);
        setKey(2,1,key);
    }

    public void setMyDigKey(HBCIKey key)
    {
        // TODO
    }
   
    public void setMyPublicSigKey(HBCIKey key)
    {
        setKey(1,0,key);
    }

    public void setMyPrivateSigKey(HBCIKey key)
    {
        setKey(1,1,key);
    }

    public void setMyPublicEncKey(HBCIKey key)
    {
        setKey(2,0,key);
    }

    public void setMyPrivateEncKey(HBCIKey key)
    {
        setKey(2,1,key);
    }

    public void setMyPublicDigKey(HBCIKey key)
    {
        // TODO
    }

    public void setMyPrivateDigKey(HBCIKey key)
    {
        // TODO
    }

    public HBCIKey getMyPublicSigKey()
    {
        return getKey(1,0);
    }

    public HBCIKey getMyPrivateSigKey()
    {
        return getKey(1,1);
    }

    public HBCIKey getMyPublicEncKey()
    {
        return getKey(2,0);
    }

    public HBCIKey getMyPrivateEncKey()
    {
        return getKey(2,1);
    }

    public HBCIKey getMyPublicDigKey()
    {
        // TODO
        return null;
    }
   
    public HBCIKey getMyPrivateDigKey()
    {
        // TODO
        return null;
    }
   
    public HBCIKey getInstSigKey()
    {
        return getKey(0,0);
    }

    public String getInstSigKeyName()
    {
        return getInstSigKey()!=null?getInstSigKey().userid:null;
    }

    public String getInstSigKeyNum()
    {
        return getInstSigKey()!=null?getInstSigKey().num:null;
    }

    public String getInstSigKeyVersion()
    {
        return getInstSigKey()!=null?getInstSigKey().version:null;
    }
   
    public HBCIKey getInstEncKey()
    {
        return getKey(0,1);
    }

    public String getInstEncKeyName()
    {
        return getInstEncKey()!=null?getInstEncKey().userid:null;
    }

    public String getInstEncKeyNum()
    {
        return getInstEncKey()!=null?getInstEncKey().num:null;
    }

    public String getInstEncKeyVersion()
    {
        return getInstEncKey()!=null?getInstEncKey().version:null;
    }

    public String getMySigKeyName()
    {
        return getMyPublicSigKey()!=null?getMyPublicSigKey().userid:null;
    }

    public String getMySigKeyNum()
    {
        return getMyPublicSigKey()!=null?getMyPublicSigKey().num:null;
    }

    public String getMySigKeyVersion()
    {
        return getMyPublicSigKey()!=null?getMyPublicSigKey().version:null;
    }

    public String getMyEncKeyName()
    {
        return getMyPublicEncKey()!=null?getMyPublicEncKey().userid:null;
    }

    public String getMyEncKeyNum()
    {
        return getMyPublicEncKey()!=null?getMyPublicEncKey().num:null;
    }

    public String getMyEncKeyVersion()
    {
        return getMyPublicEncKey()!=null?getMyPublicEncKey().version:null;
    }

    public final void setKey(int i,int j,HBCIKey key)
    {
        // System.out.println("passportRDH: setting key "+i+","+j+" to "+(key==null?"null":key.country+":"+key.blz+":"+key.cid+":"+key.num+":"+key.version));
        keys[i][j]=key;
    }
   
    public byte[] sign(byte[] data)
    {
        /* data is the result from the hash() method. In most cases, this is simply
         * the hbci message to be signed, because the signature algorithms used here
         * (iso-9796-1, iso-9796-2, pkcs#1-pss) INCLUDE the hash-step, so it must
         * not be done manually before.
         * the only exception for this is is RDH-10 where an extra round of hashing
         * must be done before using PKCS#1-PSS */
       
        try {
            Signature sig=getSignatureInstance();
            sig.initSign((PrivateKey)(getMyPrivateSigKey().key));
            sig.update(data);
            byte[] result=sig.sign();
            result=checkForCryptDataSize(result, getCryptDataSize(getMyPublicSigKey().key));
            return result;
        } catch (Exception ex) {
            throw new HBCI_Exception("*** signing of message failed",ex);
        }
    }

    public boolean verify(byte[] data,byte[] sig)
    {
        /* data is the result from the hash() method. In most cases, this is simply
         * the hbci message to be signed, because the signature algorithms used here
         * (iso-9796-1, iso-9796-2, pkcs#1-pss) INCLUDE the hash-step, so it must
         * not be done manually before.
         * the only exception for this is is RDH-10 where an extra round of hashing
         * must be done before using PKCS#1-PSS */
       
        try {
            Signature sign=getSignatureInstance();
            sign.initVerify((PublicKey)(getInstSigKey().key));
            sign.update(data);
            return sign.verify(sig);
        } catch (Exception ex) {
            throw new HBCI_Exception("*** verification of message signature failed",ex);
        }
    }

    private byte[] encryptMessage(byte[] plainMsg,SecretKey msgkey)
    {
        try {
            Cipher cipher=Cipher.getInstance("DESede/CBC/NoPadding");
            byte[] iv=new byte[8];
            Arrays.fill(iv,(byte)(0));
            IvParameterSpec spec=new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE,msgkey,spec);

            return cipher.doFinal(plainMsg);
        } catch (Exception ex) {
            throw new HBCI_Exception("*** can not encrypt message",ex);
        }
    }
   
    private byte[] encryptKey(SecretKey msgkey)
    {
        try {
            // schluessel als byte-array abspeichern

            SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
            DESedeKeySpec spec=(DESedeKeySpec)(factory.getKeySpec(msgkey,DESedeKeySpec.class));
            byte[] plainKey=spec.getKey(); // plainKey ist der DESede-Key

            // abh�ngig von der L�nge des inst-enc-keys
            int    cryptDataSize=getCryptDataSize(getInstEncKey().key);
            byte[] plainText=new byte[cryptDataSize];
            Arrays.fill(plainText,(byte)(0));
            System.arraycopy(plainKey,0,plainText,plainText.length-16,16);
            BigInteger m=new BigInteger(+1,plainText);

            Key k=getInstEncKey().key;
            BigInteger c=m.modPow(((RSAPublicKey)(k)).getPublicExponent(),
                                  ((RSAPublicKey)(k)).getModulus());
            byte[] result=c.toByteArray();
            result=checkForCryptDataSize(result, cryptDataSize);
            return result;
        } catch (Exception ex) {
            throw new HBCI_Exception("*** can not encrypt message key",ex);
        }
    }

    public byte[][] encrypt(byte[] plainMsg)
    {
        try {
            SecretKey msgkey=createMsgKey();
            byte[] cryptMsg=encryptMessage(plainMsg,msgkey);
            byte[] cryptKey=encryptKey(msgkey);

            byte[][] ret=new byte[2][];
            ret[0]=cryptKey;
            ret[1]=cryptMsg;

            return ret;
        } catch (Exception ex) {
            throw new HBCI_Exception("*** error while encrypting",ex);
        }
    }

    public byte[] decrypt(byte[] cryptedKey,byte[] cryptedMsg)
    {
        try {
            // key entschluesseln
            Key k=getMyPrivateEncKey().key;
           
            byte[] plainKey;
            if (k instanceof RSAPrivateKey) {
                HBCIUtils.log("decrypting message key with (n,d)-algorithm",HBCIUtils.LOG_DEBUG);
                BigInteger exponent=((RSAPrivateKey)(k)).getPrivateExponent();
                BigInteger modulus=((RSAPrivateKey)(k)).getModulus();

                BigInteger c=new BigInteger(+1,cryptedKey);
                plainKey=c.modPow(exponent,modulus).toByteArray();
            } else {
                HBCIUtils.log("decrypting message key with (p,q,dP,dQ,qInv)-algorithm",HBCIUtils.LOG_DEBUG);
                BigInteger p=((RSAPrivateCrtKey2)k).getP();
                BigInteger q=((RSAPrivateCrtKey2)k).getQ();
                BigInteger dP=((RSAPrivateCrtKey2)k).getdP();
                BigInteger dQ=((RSAPrivateCrtKey2)k).getdQ();
                BigInteger qInv=((RSAPrivateCrtKey2)k).getQInv();
       
                BigInteger c=new BigInteger(+1,cryptedKey);
                BigInteger m1=c.modPow(dP,p);
                BigInteger m2=c.modPow(dQ,q);
                BigInteger h=m1.subtract(m2).multiply(qInv).mod(p);
                plainKey=m2.add(q.multiply(h)).toByteArray();
            }

            byte[] realPlainKey=new byte[24];
            System.arraycopy(plainKey,plainKey.length-16,realPlainKey,0,16);
            System.arraycopy(plainKey,plainKey.length-16,realPlainKey,16,8);

            DESedeKeySpec spec=new DESedeKeySpec(realPlainKey);
            SecretKeyFactory fac=SecretKeyFactory.getInstance("DESede");
            SecretKey key=fac.generateSecret(spec);

            // nachricht entschluesseln
            Cipher cipher=Cipher.getInstance("DESede/CBC/NoPadding");
            byte[] ivarray=new byte[8];
            Arrays.fill(ivarray,(byte)(0));
            IvParameterSpec iv=new IvParameterSpec(ivarray);
            cipher.init(Cipher.DECRYPT_MODE,key,iv);
            return cipher.doFinal(cryptedMsg);
        } catch (Exception ex) {
            throw new HBCI_Exception("*** error while decrypting message",ex);
        }
    }
   
    private int getKeySizeByProfile()
    {
        int ret=-1;
        int profile=Integer.parseInt(getProfileVersion());
       
        switch (profile) {
        case 1:
            ret=768;
            break;
        case 2:
            ret=2048;
            break;
        case 10:
            HBCIKey k=getInstSigKey();
            if (k==null) {
                k=getInstEncKey();
            }
            if (k!=null) {
                RSAPublicKey pkey=(RSAPublicKey)k.key;
                ret = pkey.getModulus().bitLength();
            } else {
                ret=4096;
            }
            break;
        default:
            throw new HBCI_Exception("*** dont know which keysize to use for profile rdh-"+profile);
        }
       
        HBCIUtils.log("using keysize "+ret+" bits for newly generated keys",HBCIUtils.LOG_DEBUG);
        return ret;
    }

    public HBCIKey[][] generateNewUserKeys()
    {
        HBCIKey[] newSigKey=null;
        HBCIKey[] newEncKey=null;
        try {
            HBCIUtils.log("generating new user keys",HBCIUtils.LOG_INFO);

            String blz=getBLZ();
            String country=getCountry();
            String userid=getUserId();
            String profileVersion=getProfileVersion();

            newSigKey=new HBCIKey[2];
            newEncKey=new HBCIKey[2];
           
            String num=hasMySigKey()?getMyPublicSigKey().num:profileVersion;
            String version=hasMySigKey()?getMyPublicSigKey().version:"0";
            version=Integer.toString(Integer.parseInt(version)+1);
           
            int keySize=getKeySizeByProfile();

            // TODO: auch dig key neu generieren?
            for (int i=0;i<2;i++) {
                KeyPairGenerator keygen=KeyPairGenerator.getInstance("RSA");
                // die schl�ssell�nge ist vom sicherheitsprofil abh�ngig
                keygen.initialize(keySize);
                KeyPair pair=keygen.generateKeyPair();

                if (i==0) {
                    newSigKey[0]=new HBCIKey(country,blz,userid,num,version,pair.getPublic());
                    newSigKey[1]=new HBCIKey(country,blz,userid,num,version,pair.getPrivate());
                } else {
                    newEncKey[0]=new HBCIKey(country,blz,userid,num,version,pair.getPublic());
                    newEncKey[1]=new HBCIKey(country,blz,userid,num,version,pair.getPrivate());
                }
            }
        } catch (Exception ex) {
            throw new HBCI_Exception(HBCIUtilsInternal.getLocMsg("EXCMSG_GENKEYS_ERR"),ex);
        }
       
        HBCIKey[][] ret=new HBCIKey[3][];
        ret[0]=newSigKey;
        ret[1]=newEncKey;
        // TODO: dig keys
        ret[2]=null;
       
        return ret;
    }
}
TOP

Related Classes of org.kapott.hbci.passport.AbstractRDHSWPassport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.