Java - Neispravan digitalni potpis (s004)

Feb 19, 2013 at 8:04 AM
Pozdrav svima!
Vec tjedan dana pokusavam ispravno poslati poruku u Javi no konstantno dobivam odgovor da mi je neispravan digitalni potpis. Ako netko zna u cemu bi mogao biti problem bio bih mu iznimno zahvalan.

Pokusavao sam sa Java rjesenjem od kolege (Signer.java) sa kojim dobijem neispravan potpis. Kada isti xml provucem kroz Raverus ispravno se posalje poruka i ne dobijem poruku o greski. Provjerio sam DigestValue te SignatureValue i u oba slucaja su mi vrijednosti identicne tako da pretpostavljam da je problem u samom slaganju poruke (formatiranju) a ne u potpisivanju. No kako nemam nikakvog iskustva sa security modulima ne znam sto da ucinim...
Da li je netko bez problema uspio potpisati i poslati poruku sa koleginim kodom?

Takodjer sam pokusavao sa nekoliko razlicitih samostalnih implementacija no niti u jednom slucaju nisam uspio dobiti zeleno svjetlo sa servera.

Evo nekoliko detalja:
  • koristim dvije transformacije (enveloped, excl-c14n)
  • kanonikalizacija (exclusive)
  • digest method (SHA1)
  • signature method (RSA_SHA1)
  • pokusavao sam sa nekoliko keystoreova, nije mi funkcioniralo ni kada sam pfx prebacio u jks (niti pomocu keytool-a niti sa metodom koju je opisao kolega). Isti xml i keystore prodju sa Raverusom.
    U principu je sve identicno izvornom kodu uz promjenu file-ova iz kojih se cita keystore i xml za potpis
Bilo kakav savjet je dobrodosao :(
Unaprijed hvala!
Feb 19, 2013 at 9:59 AM
Edited Feb 19, 2013 at 10:00 AM
evo dio mog java koda koji radi:
//Lista transformacija u potpisu

List transforms  = new ArrayList<Transform>() {{
    add(sigFactory.newTransform(
                Transform.ENVELOPED,
                (TransformParameterSpec) null
            )
        );
    TransformParameterSpec transformSpec = null;
      Transform envTransform = sigFactory.newTransform(
          "http://www.w3.org/2001/10/xml-exc-c14n#",transformSpec);
     
    add(envTransform);
}};

//Refenca koja pokazuje id elementa koji je potpisani i korištene algoritme

Reference ref = sigFactory.newReference
        ( "#" + polje + "",
            sigFactory.newDigestMethod(DigestMethod.SHA1, null),
            transforms,
            null,
            null);
Feb 19, 2013 at 10:40 AM
fico7489 wrote:
evo dio mog java koda koji radi:
Na zalost tako i ja radim :(
Ne kuzim...kao sto sam rekao, cini se da je sam potpis ok posto dobijem digestvalue i signaturevalue identicne onima koje dobijem i sa Raverus alatom.
Zbog toga sumnjam da mi je krivi input xml (jer isti radi sa Raverusom), no ipak, na koji nacin radis marshalling?
Ovo je moj kod ("zahtjev" je "PoslovniProstorZahtjev" objekt:
OutputStream os = new ByteOutputStream();
JAXBContext context = JAXBContext.newInstance("com.fina.schema");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE); //probao i sa FALSE...
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); //probao i sa FALSE...
marshaller.marshal(zahtjev, os);
return os.toString(); //taj string zapisem u file.xml i onda njega potpisujem i potpisano stavljam u SOAPMessage
Kod za kreiranje SOAPMessage objekta je identican onome od kolege u Signer.java klasi (sa drugim keystoreovima setanim u System.properties)
Signer.java
Koristis isti taj kod za slanje poruke i sve ti radi ok?

Hvala na trudu!
Feb 19, 2013 at 11:08 AM
Imao sam isti problem i riješio tako da sam napravim kanonizaciju jer jrs105 (ili kako se već zove taj lib.) ne napravi ispravno.
Feb 19, 2013 at 11:33 AM
Da li mi mozes pojasniti sa kakvim hint-om kako si to napravio? (prvi puta se susrecem sa tim libom, signanjem xml-a i slicnim stvarima...)
Stvarno ne bih molio za pomoc no nakon tjedan dana bezuspjesnih pokusaja totalno sam ocajan.
Feb 19, 2013 at 1:43 PM
Edited Feb 19, 2013 at 2:35 PM
Ne znam u kojoj firmi radis, ili se samo igras, ali evo dva linka, mozda pomognu:

9203478

534574

ako ne pomognu, mozes me privatno kontaktirati pa cu te spojiti sa kolegom koji je radio te stvari.

I
Feb 19, 2013 at 2:12 PM
Nisam koristio klasu Marshaller nego SOAPConnection, a ima tu puno problema na koje sam naišao, radio sam to dosta dugo samo uz pomoć googla, nitko mi nije pomagao jer onda još nitko nije to radio u Javi.
Tako da bi mi sad trebalo par stranica da ti to sve opišem.
Na kraju sam ipak uspio sve to napraviti da radi s Openbravom...
Feb 19, 2013 at 3:44 PM
Hvala puno obojici na trudu.
@fico - nema veze, valjda cu se nekako snaci
@idelac - da, pokusao sam i stripati string kao sto je u tim primjerima pojasnjeno no bez uspjeha (to stripanje se i koristi u Signer.java klasi no i sa tim mi nije radilo...)

Trenutno pokusavam signati sa Apache Santurio library-em pa ce valjda tamo biti vise srece. A siguran sam da se radi o nekoj sitnici koju ne vidim i jednostavno ju ne mogu pronaci...
Feb 20, 2013 at 11:00 AM
Edited Feb 20, 2013 at 1:17 PM
Nakon tjedan dana muke uspio sam potpisati xml...
Da se netko drugi ne bi mucio kao ja evo nekoliko smjernica kako sam ja to napravio.

1) Izgenerirao sam klase sa wsdl2java
2) Instancirao sam objekt PoslovniProstorZahtjev i marshallao ga da dobijem xml string (string nije formatiran i nema extra razmaka):
OutputStream os = new ByteOutputStream();
JAXBContext context = JAXBContext.newInstance("com.fina.schema");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.FALSE);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.marshal(zahtjev, os);
String result = os.toString();
os.close();
return result;
3) taj string sam spremio u file i ucitao ga te signao koristeci klasu Signer.java od kolege Igor Cuncica (ne morate spremati u file i ucitavati iz fajla kao u Signer.java klasi ako ste ga marshallali na gore navedeni nacin posto ce vec biti u ispravnom formatu)
3a) keystore nisam prebacivao u jks format, kako je kolega preporucavao, nego sam koristio pfx format (samo sam definirao da je keystore type "PKCS12")

4) Sve je radilo fantasticno osim dijela sa samim slanjem poruke. Stoga sam poruku slozio na sljedeci nacin:
SOAPPart soapPart =     message.getSOAPPart();  
            
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer2 = tf.newTransformer();
transformer2.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StringWriter writer = new StringWriter();
transformer2.transform(new DOMSource(doc), new StreamResult(writer));
String output = writer.getBuffer().toString().replaceAll("\n|\r", "");
            
//adding envelope part
String completeMessage = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchemainstance\"><soapenv:Body>"+
output+
"</soapenv:Body></soapenv:Envelope>";
            
System.out.println(completeMessage);
PrintWriter out5 = new PrintWriter("D:\\FINA\\temp.txt");
out5.print(completeMessage);
out5.close();
StreamSource prepMsg = new StreamSource(new FileInputStream("D:\\FINA\\temp.txt"));
soapPart.setContent(prepMsg);  
message.writeTo(System.out);  
URL destination = new URL("https://cistest.apis-it.hr:8449/FiskalizacijaServiceTest");
SOAPMessage reply = connection.call(message, destination);
Tu sada ima puno "smeca" jer se pise pa cita iz fajla, to bi se sve dalo popraviti. Takodjer je problematican dio sa rucnim dodavanjem soap envelopea...

Eto, ako ideja/rjesenje uspije nekome pomoci, super!
Oct 3, 2013 at 10:20 PM
Već sam totalno lud.... jel neko uspio konvertirati .pfx ili .p12 u .bks koji je potreban za rad s android sustavom.... Please help....
Oct 4, 2013 at 7:44 AM
Ne znam za Android, ali za desktop Javu ovako ide učitavanje pfx/p12 datoteke direktno bez konverzija u jks ili neki drugi format:
   private static KeyStore keyStore;

   public void loadKeyStore(String keyFile, String keyPassword) {

        PrivateKeyEntry keyEntry = null;

        // objekt keyStore, koriste proc. za potpisivanje i provjeru potpisa,
        //  i procedura za izracun zastitnog koda
        try {
            // ucitaj jks datoteku
            keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(new FileInputStream(keyFile), keyPassword.toCharArray());

            // uzmi kljuc iz pfx datoteke
            keyEntry = (PrivateKeyEntry) keyStore.getEntry(keyStore.aliases().nextElement(),
                    new KeyStore.PasswordProtection(keyPassword.toCharArray()));
            cert = (X509Certificate) keyEntry.getCertificate();
            publicKey = cert.getPublicKey();
            privateKey = keyEntry.getPrivateKey();

            if (cert.getSubjectAlternativeNames() != null) {
                Collection altNames = cert.getSubjectAlternativeNames();
                List item = (List) altNames.iterator().next();
                email = (String) item.get(1);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }