Skip to content
This repository has been archived by the owner on May 16, 2018. It is now read-only.

Commit

Permalink
Das Parsen des empfangenen SEPA-PAIN darf nicht pauschal mit UTF-8
Browse files Browse the repository at this point in the history
erfolgen sondern mit dem Zeichensatz, mit dem die Daten vom Server
empfangen wurden. Siehe auch der ausfuehrliche Text in GVTermUebSEPAList
Unit-Test TestPainGen#test006 hinzugefuegt.
  • Loading branch information
willuhn committed May 30, 2014
1 parent 9cf329c commit 90e5b37
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 48 deletions.
3 changes: 2 additions & 1 deletion src/org/kapott/hbci/GV/AbstractSEPAGV.java
Expand Up @@ -12,6 +12,7 @@
import org.kapott.hbci.GV.generators.ISEPAGenerator;
import org.kapott.hbci.GV.generators.SEPAGeneratorFactory;
import org.kapott.hbci.GV_Result.HBCIJobResultImpl;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIHandler;
import org.kapott.hbci.manager.HBCIUtils;
Expand Down Expand Up @@ -336,7 +337,7 @@ protected void createSEPAFromParams()
throw new HBCI_Exception("*** the _sepapain segment for this job can not be created");

try {
String xml = o.toString("ISO-8859-1");
String xml = o.toString(Comm.ENCODING);
HBCIUtils.log("generated XML:\n" + xml,HBCIUtils.LOG_DEBUG);
setParam("_sepapain", "B" + xml);
}
Expand Down
17 changes: 9 additions & 8 deletions src/org/kapott/hbci/GV/GVDauerSEPAList.java
Expand Up @@ -22,14 +22,15 @@
package org.kapott.hbci.GV;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;

import org.kapott.hbci.GV.parsers.ISEPAParser;
import org.kapott.hbci.GV.parsers.SEPAParserFactory;
import org.kapott.hbci.GV_Result.GVRDauerList;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIHandler;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.manager.LogFilter;
Expand Down Expand Up @@ -107,14 +108,14 @@ protected void extractResults(HBCIMsgStatus msgstatus,String header,int idx)
ISEPAParser parser = SEPAParserFactory.get(version);
ArrayList<Properties> sepaResults = new ArrayList<Properties>();
String pain = result.getProperty(header+".sepapain");
InputStream is = null;
try {
is = new ByteArrayInputStream(pain.getBytes("UTF-8"));
parser.parse(is, sepaResults);
try
{
// Encoding siehe GVTermUebSEPAList
parser.parse(new ByteArrayInputStream(pain.getBytes(Comm.ENCODING)), sepaResults);
}
catch(Exception e) {
HBCIUtils.log("Error parsing SEPA pain document: ", HBCIUtils.LOG_ERR);
HBCIUtils.log(e);
catch(Exception e)
{
throw new HBCI_Exception("Error parsing SEPA pain document",e);
}

if(sepaResults.isEmpty()) return;
Expand Down
26 changes: 18 additions & 8 deletions src/org/kapott/hbci/GV/GVTermUebSEPAList.java
Expand Up @@ -22,14 +22,15 @@
package org.kapott.hbci.GV;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;

import org.kapott.hbci.GV.parsers.ISEPAParser;
import org.kapott.hbci.GV.parsers.SEPAParserFactory;
import org.kapott.hbci.GV_Result.GVRTermUebList;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIHandler;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.manager.LogFilter;
Expand Down Expand Up @@ -108,14 +109,23 @@ protected void extractResults(HBCIMsgStatus msgstatus,String header,int idx)
ISEPAParser parser = SEPAParserFactory.get(version);
ArrayList<Properties> sepaResults = new ArrayList<Properties>();
String pain = result.getProperty(header+".sepapain");
InputStream is = null;
try {
is = new ByteArrayInputStream(pain.getBytes("UTF-8"));
parser.parse(is, sepaResults);
try
{
// Wir duerfen das hier nicht als UTF-8 interpretieren (das war vorher hier das Fall),
// auch dann nicht, wenn wir genau wissen, dass das XML mit "<?xml version="1.0" encoding="UTF-8"?>"
// beginnt. Stattdessen muessen wir den selben Zeichensatz nehmen, der bei der Byte->String Conversion
// beim Empfamg der rohen HBCI-Daten ueber TCP verwendet wurde. Siehe CommStandard/CommPinTan.
// Die eigentliche Codierung der XML-Datei spielt hier keine Rolle - wichtig ist, dass die
// Rueckwandlung String->Bytes (in pain.getBytes) den selben Zeichensatz verwendet wie beim Empfang der
// Daten vom Server. Nur so ist sichergestellt, dass die Bytes wieder genauso aussehen, wie sie
// beim Empfang vom Server kamen, wenn der XML-Parser sie kriegt. Er macht dann die Conversion Byte->String
// korrekt basierend auf dem im XML angegebenen Header.
// Siehe auch AbstractSEPAGenerator#marshal
parser.parse(new ByteArrayInputStream(pain.getBytes(Comm.ENCODING)), sepaResults);
}
catch(Exception e) {
HBCIUtils.log("Error parsing SEPA pain document: ", HBCIUtils.LOG_ERR);
HBCIUtils.log(e);
catch(Exception e)
{
throw new HBCI_Exception("Error parsing SEPA pain document",e);
}

if(sepaResults.isEmpty()) return;
Expand Down
17 changes: 16 additions & 1 deletion src/org/kapott/hbci/GV/generators/AbstractSEPAGenerator.java
Expand Up @@ -14,6 +14,7 @@
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.sepa.PainVersion;

Expand All @@ -39,9 +40,23 @@ public abstract class AbstractSEPAGenerator implements ISEPAGenerator
*/
protected void marshal(JAXBElement e, OutputStream os, boolean validate) throws Exception
{
// Wir verwenden per Default nicht mehr UTF-8 zum Codieren sondern ISO-8859-1.
// Zum einen ist das gemaess Anlage3_Datenformate_V2.7.pdf (Seite 22, Zeichensaetze)
// der Default-Zeichensatz (obschon auch UTF-8) erlaubt ist. Da die HBCI-Message
// selbst aber seit jeher mit ISO-8859-1 ueber die Leitung geschickt wird (siehe CommPinTan
// und CommStandard), wuerde das sonst eine ISO-8859-1 HBCI-Nachricht ergeben, die
// ein Binaer-DE enthaelt, welches das XML enthaelt und welches dann aber als UTF-8
// codiert ist. Bei XML mag das noch gehen, weil das XML ja im Header den verwendeten
// Zeichensatz selbst mitbringt. Bei anderen Datenarten, kann das aber zu Problemen fuehren
//
// Da ich hiermit aber das Default-Verhalten aendere (vorher stand hier hart "UTF-8"),
// mache ich es per System-Property konfigurierbar.
final String charset = System.getProperty("sepa.pain.charset",Comm.ENCODING);
LOG.fine("using charset " + charset);

JAXBContext jaxbContext = JAXBContext.newInstance(e.getDeclaredType());
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_ENCODING, charset);

// Siehe https://groups.google.com/d/msg/hbci4java/RYHCai_TzHM/72Bx51B9bXUJ
if (System.getProperty("sepa.pain.formatted","false").equalsIgnoreCase("true"))
Expand Down
5 changes: 5 additions & 0 deletions src/org/kapott/hbci/comm/Comm.java
Expand Up @@ -40,6 +40,11 @@

public abstract class Comm
{
/**
* Der zu verwendende Zeichensatz.
*/
public final static String ENCODING = "ISO-8859-1";

protected Filter filter;
private HBCIPassportInternal parentPassport;

Expand Down
2 changes: 1 addition & 1 deletion src/org/kapott/hbci/comm/CommPinTan.java
Expand Up @@ -171,7 +171,7 @@ protected StringBuffer pong(MsgGen gen)

while (msgsize!=0 && (num=i.read(b))>0) {
HBCIUtils.log("received "+num+" bytes",HBCIUtils.LOG_DEBUG2);
ret.append(new String(b,0,num,"ISO-8859-1"));
ret.append(new String(b,0,num,ENCODING));
msgsize-=num;
if (msgsize>=0) {
HBCIUtils.log("we still need "+msgsize+" bytes",HBCIUtils.LOG_DEBUG2);
Expand Down
4 changes: 2 additions & 2 deletions src/org/kapott/hbci/comm/CommStandard.java
Expand Up @@ -114,7 +114,7 @@ protected StringBuffer pong(MsgGen gen)
while ((!sizeknown || msgsize>0) && (num=i.read(b))!=-1) {
HBCIUtils.log("received "+num+" bytes",HBCIUtils.LOG_DEBUG2);

String st=new String(b,0,num,"ISO-8859-1");
String st=new String(b,0,num,ENCODING);

ret.append(st);

Expand All @@ -138,7 +138,7 @@ protected StringBuffer pong(MsgGen gen)
}

// FileOutputStream fo=new FileOutputStream("pong.dat");
// fo.write(ret.toString().getBytes("ISO-8859-1"));
// fo.write(ret.toString().getBytes(ENCODING));
// fo.close();

return new StringBuffer(filter.decode(ret.toString()));
Expand Down
4 changes: 2 additions & 2 deletions src/org/kapott/hbci/comm/FilterBase64.java
Expand Up @@ -36,7 +36,7 @@ public FilterBase64()
public String decode(String st)
{
try {
return new String(HBCIUtils.decodeBase64(st),"ISO-8859-1");
return new String(HBCIUtils.decodeBase64(st),Comm.ENCODING);
} catch (Exception e) {
throw new HBCI_Exception(HBCIUtilsInternal.getLocMsg("EXCMSG_B64DECODEERR"),e);
}
Expand All @@ -45,7 +45,7 @@ public String decode(String st)
public byte[] encode(String st)
{
try {
return HBCIUtils.encodeBase64(st.getBytes("ISO-8859-1")).getBytes("ISO-8859-1");
return HBCIUtils.encodeBase64(st.getBytes(Comm.ENCODING)).getBytes(Comm.ENCODING);
} catch (Exception ex) {
throw new HBCI_Exception(HBCIUtilsInternal.getLocMsg("EXCMSG_B64ENCODEERR"),ex);
}
Expand Down
2 changes: 1 addition & 1 deletion src/org/kapott/hbci/comm/FilterNone.java
Expand Up @@ -36,7 +36,7 @@ public FilterNone()
public byte[] encode(String st)
{
try {
return st.getBytes("ISO-8859-1");
return st.getBytes(Comm.ENCODING);
} catch (Exception e) {
throw new HBCI_Exception(HBCIUtilsInternal.getLocMsg("EXCMSG_ISOERR"),e);
}
Expand Down
2 changes: 1 addition & 1 deletion src/org/kapott/hbci/comm/HBCI4JavaLogOutputStream.java
Expand Up @@ -64,7 +64,7 @@ public void flush()
throws IOException
{
if (this.logdata.size()!=0) {
HBCIUtils.log("socket log: "+this.logdata.toString("ISO-8859-1"), HBCIUtils.LOG_DEBUG2);
HBCIUtils.log("socket log: "+this.logdata.toString(Comm.ENCODING), HBCIUtils.LOG_DEBUG2);
}
this.logdata.reset();
}
Expand Down
3 changes: 2 additions & 1 deletion src/org/kapott/hbci/datatypes/SyntaxBin.java
Expand Up @@ -23,6 +23,7 @@

import java.math.BigInteger;

import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.InvalidArgumentException;
import org.kapott.hbci.exceptions.InvalidUserDataException;
import org.kapott.hbci.manager.HBCIUtilsInternal;
Expand Down Expand Up @@ -56,7 +57,7 @@ public class SyntaxBin
private static String expandNumber(String x)
{
try {
return new String((new BigInteger(x)).toByteArray(),"ISO-8859-1");
return new String((new BigInteger(x)).toByteArray(),Comm.ENCODING);
} catch (Exception ex) {
throw new InvalidUserDataException(HBCIUtilsInternal.getLocMsg("EXCMSG_BINNUMERR"),ex);
}
Expand Down
5 changes: 3 additions & 2 deletions src/org/kapott/hbci/manager/HBCIInstitute.java
Expand Up @@ -31,6 +31,7 @@
import java.util.Properties;

import org.kapott.hbci.callback.HBCICallback;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.exceptions.InvalidUserDataException;
import org.kapott.hbci.exceptions.ProcessException;
Expand Down Expand Up @@ -116,8 +117,8 @@ void extractKeys(Properties result)
keyNum+"_"+keyVersion,
HBCIUtils.LOG_INFO);

byte[] keyExponent=result.getProperty(head+".PubKey.exponent").getBytes("ISO-8859-1");
byte[] keyModulus=result.getProperty(head+".PubKey.modulus").getBytes("ISO-8859-1");
byte[] keyExponent=result.getProperty(head+".PubKey.exponent").getBytes(Comm.ENCODING);
byte[] keyModulus=result.getProperty(head+".PubKey.modulus").getBytes(Comm.ENCODING);

KeyFactory fac=KeyFactory.getInstance("RSA");
KeySpec spec=new RSAPublicKeySpec(new BigInteger(+1,keyModulus),
Expand Down
5 changes: 3 additions & 2 deletions src/org/kapott/hbci/manager/HBCIUser.java
Expand Up @@ -28,6 +28,7 @@
import java.util.Properties;

import org.kapott.hbci.callback.HBCICallback;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.exceptions.NeedKeyAckException;
import org.kapott.hbci.exceptions.ProcessException;
Expand Down Expand Up @@ -120,15 +121,15 @@ private void sendAndActivateNewUserKeys(HBCIKey[] sigKey,HBCIKey[] encKey)
while (startpos<len && ba[startpos]==0) {
startpos++;
}
exponent[i] = new String(ba,startpos,len-startpos,"ISO-8859-1");
exponent[i] = new String(ba,startpos,len-startpos,Comm.ENCODING);

ba=spec.getModulus().toByteArray();
len=ba.length;
startpos=0;
while (startpos<len && ba[startpos]==0) {
startpos++;
}
modulus[i] = new String(ba,startpos,len-startpos,"ISO-8859-1");
modulus[i] = new String(ba,startpos,len-startpos,Comm.ENCODING);
}

if (!passport.hasMySigKey()) {
Expand Down
3 changes: 2 additions & 1 deletion src/org/kapott/hbci/manager/HBCIUtils.java
Expand Up @@ -43,6 +43,7 @@
import org.kapott.cryptalgs.CryptAlgs4JavaProvider;
import org.kapott.hbci.GV_Result.GVRKUms;
import org.kapott.hbci.callback.HBCICallback;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.exceptions.InvalidArgumentException;
import org.kapott.hbci.exceptions.InvalidUserDataException;
Expand Down Expand Up @@ -1420,7 +1421,7 @@ public static String encodeBase64(byte[] x)
public static byte[] decodeBase64(String st)
{
try {
byte[] source=st.getBytes("ISO-8859-1");
byte[] source=st.getBytes(Comm.ENCODING);
byte[] ret=new byte[st.length()];
int retlen=0;

Expand Down
7 changes: 4 additions & 3 deletions src/org/kapott/hbci/manager/InfoPointConnector.java
Expand Up @@ -42,6 +42,7 @@
import javax.xml.transform.stream.StreamResult;

import org.kapott.hbci.callback.HBCICallback;
import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.passport.HBCIPassportInternal;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
Expand Down Expand Up @@ -165,7 +166,7 @@ private String prepareXMLDocument(String xmlType, Properties passportData, Prope
rootElem.appendChild(bpdElem);

// store BPD in element
String bpd_encoded=HBCIUtils.encodeBase64(bpd_st.getBytes("ISO-8859-1"));
String bpd_encoded=HBCIUtils.encodeBase64(bpd_st.getBytes(Comm.ENCODING));
bpdElem.appendChild(doc.createTextNode(bpd_encoded));

// create XML string
Expand All @@ -174,15 +175,15 @@ private String prepareXMLDocument(String xmlType, Properties passportData, Prope

trans.setOutputProperty(OutputKeys.METHOD, "xml");
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
trans.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
trans.setOutputProperty(OutputKeys.ENCODING, Comm.ENCODING);
trans.setOutputProperty(OutputKeys.INDENT, "yes");

Source source=new DOMSource(doc);
ByteArrayOutputStream xmlStream=new ByteArrayOutputStream();
Result target=new StreamResult(xmlStream);

trans.transform(source, target);
return xmlStream.toString("ISO-8859-1");
return xmlStream.toString(Comm.ENCODING);
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
4 changes: 2 additions & 2 deletions src/org/kapott/hbci/passport/AbstractPinTanPassport.java
Expand Up @@ -1078,10 +1078,10 @@ private void patchMessagesFor2StepMethods(HBCIDialog dialog)
HBCIUtils.log("using "+alg+"/"+provider+" for generating order hash", HBCIUtils.LOG_DEBUG);
MessageDigest digest=MessageDigest.getInstance(alg,provider);

digest.update(segdata.getBytes("ISO-8859-1"));
digest.update(segdata.getBytes(Comm.ENCODING));
byte[] hash=digest.digest();
SEGFactory.getInstance().unuseObject(seg);
hktan.setParam("orderhash",new String(hash,"ISO-8859-1"));
hktan.setParam("orderhash",new String(hash,Comm.ENCODING));
} catch (Exception e) {
throw new HBCI_Exception(e);
}
Expand Down
13 changes: 7 additions & 6 deletions src/org/kapott/hbci/security/Crypt.java
Expand Up @@ -25,6 +25,7 @@
import java.util.Date;
import java.util.List;

import org.kapott.hbci.comm.Comm;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.manager.HBCIUtilsInternal;
Expand Down Expand Up @@ -117,7 +118,7 @@ private byte[] getPlainString()
}
ret.append((char)(padLength));

return ret.toString().getBytes("ISO-8859-1");
return ret.toString().getBytes(Comm.ENCODING);
} catch (Exception ex) {
throw new HBCI_Exception("*** error while extracting plain message string",ex);
}
Expand Down Expand Up @@ -159,10 +160,10 @@ public MSG cryptIt(String newName)

Date d=new Date();

gen.set(newName+".CryptData.data","B"+new String(crypteds[1],"ISO-8859-1"));
gen.set(newName+".CryptData.data","B"+new String(crypteds[1],Comm.ENCODING));
gen.set(newName+".CryptHead.CryptAlg.alg",u_alg);
gen.set(newName+".CryptHead.CryptAlg.mode",u_mode);
gen.set(newName+".CryptHead.CryptAlg.enckey","B"+new String(crypteds[0],"ISO-8859-1"));
gen.set(newName+".CryptHead.CryptAlg.enckey","B"+new String(crypteds[0],Comm.ENCODING));
gen.set(newName+".CryptHead.CryptAlg.keytype",u_keytype);
gen.set(newName+".CryptHead.SecIdnDetails.func",(newmsg.getName().endsWith("Res")?"2":"1"));
gen.set(newName+".CryptHead.KeyName.KIK.blz",u_blz);
Expand Down Expand Up @@ -257,12 +258,12 @@ public String decryptIt()

// verschluesselte daten extrahieren
SEG cryptdata=(SEG)(((MultipleSEGs)(childs.get(2))).getElements().get(0));
byte[] cryptedstring=cryptdata.getValueOfDE(msgName+".CryptData.data").getBytes("ISO-8859-1");
byte[] cryptedstring=cryptdata.getValueOfDE(msgName+".CryptData.data").getBytes(Comm.ENCODING);

// key extrahieren
SEG crypthead=(SEG)(((MultipleSEGs)(childs.get(1))).getElements().get(0));
byte[] cryptedkey=crypthead.getValueOfDE(msgName+
".CryptHead.CryptAlg.enckey").getBytes("ISO-8859-1");
".CryptHead.CryptAlg.enckey").getBytes(Comm.ENCODING);

// neues secfunc (klartext/encrypted)
String secfunc=crypthead.getValueOfDE(msgName+".CryptHead.secfunc");
Expand Down Expand Up @@ -329,7 +330,7 @@ public String decryptIt()
// neuen nachrichtenstring zusammenbauen
ret=new StringBuffer(1024);
ret.append(msghead.toString(0)).
append(new String(plainMsg,0,plainMsg.length-padLength,"ISO-8859-1")).
append(new String(plainMsg,0,plainMsg.length-padLength,Comm.ENCODING)).
append(msgtail.toString(0));

HBCIUtils.log("decrypted message: "+ret,HBCIUtils.LOG_DEBUG2);
Expand Down

0 comments on commit 90e5b37

Please sign in to comment.