Komunikacja z Epuap - podpis Xades

0

Witam
Borykam się już od pewnego czasu z implementacją komunikacji z portalem ePuap w Java, a dokładniej chodzi mi o zaimplementowanie całej ich koperty SOAP do komunikacji. Szukając w internecie okazało się że nie ma tego wiele. Bardzo pomocna była strona http://www.extern.pl/artykuly/ws-security_epuap/. Na początku zabrnąłem niestety w ślepą uliczkę (przynajmniej tak mi się wydaje) bo do podpisu używałem biblioteki WSS4J, niestety jak się okazuje Xades to chyba troszeczkę coś innego. Przy WSS4J używałem takiego kodu

WSSConfig.init();
		
		String soapXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
				"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:user=\"http://userinfo.zp.epuap.gov.pl\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
				"<SOAP-ENV:Body xmlns:ns=\"http://ejb.draco.comarch.com\">" +
					"<ns:getUserInfo>" +
						"<ns:tgsId></ns:tgsId>" +					
						"<ns:appId></ns:appId>" +
					"</ns:getUserInfo>" +
				"</SOAP-ENV:Body>" +
				"</SOAP-ENV:Envelope>";
		
		Document doc = SOAPUtil.toSOAPPart(soapXML);
		
		
		
		Properties clientProperties = new Properties();
        clientProperties.put("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.type", "jks");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.password", "haslo");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.alias", "alias");
        clientProperties.put("org.apache.wss4j.crypto.merlin.keystore.file", "plik.jks");
        
        Crypto crypto = new Merlin(clientProperties, this.getClass().getClassLoader(), null);
			
		WSSecHeader secHeader = new WSSecHeader();
		secHeader.insertSecurityHeader(doc);        
		
		WSSecTimestamp timestamp = new WSSecTimestamp();
		timestamp.setTimeToLive(3 * 3600);
		doc = timestamp.build(doc, secHeader);				
		
	        
		WSSecSignature builder = new WSSecSignature();
		builder.setUserInfo("uzytkownik", "haslo");	
		builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
		
		List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
        WSEncryptionPart encP = new WSEncryptionPart("Timestamp", WSConstants.WSU_NS,"");
        WSEncryptionPart bodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "");
        parts.add(bodyPart);
        parts.add(encP);
        builder.setParts(parts);   
		
		Document signedDoc = builder.build(doc, crypto, secHeader);
 

W wyniku czego dostawałem taką kopertę:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:user="http://userinfo.zp.epuap.gov.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
         <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" Id="e6bac805-2ee5-4d82-8e8e-ee4c0a37e705" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIICSjCCAbOgAwIBAgIJAIXSDNq9Dr0hMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNVBAYTAlBMMR4wHAYDVQQKExVDUEkgQ0EgZm9yIGVwdWFwIFRFU1QxHjAcBgNVBAsTFUNQSSBDQSBmb3IgZXB1YXAgVEVTVDEeMBwGA1UEAxMVQ1BJIENBIGZvciBlcHVhcCBURVNUMB4XDTE0MDgxNTAwMDAwMFoXDTE2MDgxNDIzNTk1OVowRTELMAkGA1UEBhMCUEwxDDAKBgNVBAoTA0NQSTETMBEGA1UECxMKZGFtaWFuU29mdDETMBEGA1UEAxMKZGFtaWFuU29mdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzXr0F9mUTQ5Ow4XqwEpCEsGZKBG+OrSmqFzFpC+gC23L96gnFYVGl5Cv5vT8fMnRlb9m7ebsH7bVFL1UsRbg4xyRi8Rf/kefSGOZmtmQG3X1BsfLsYfhXBhYC8qvjJfnm8pVaHZ1joxcUapzwTQp2Se/EFTAodJV24JL8T8XdXcCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADgYEAF2+pSbCJzxg0Zd75fO0zNviPvZJU6FD2aq6YQGKGghMSfBXH6M3oX6AdHWD9nXrvGCqB6aNBdeww1RbF7qOugUYxmZ6fqxVRwADrSP81Uz8rLBQVovieCjlXdeWvXt4CGyeu1AcdXYMnsdTtvXHHAdAoqMTP+klPAM0MrsN+GRA=</wsse:BinarySecurityToken>
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-444db4cb-7f98-469a-acc5-f15470eaf298">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                  <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENC SOAP-ENV user xsd xsi" />
               </ds:CanonicalizationMethod>
               <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
               <ds:Reference URI="#id-de9cadef-6ab1-4f68-9106-b7c87ed85a95">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENC user xsd xsi" />
                     </ds:Transform>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue>QGFHPvQm0xoKx6UfJioDhycuvzg=</ds:DigestValue>
               </ds:Reference>
               <ds:Reference URI="#TS-15747850-9adf-4990-a5ee-8c23bb50ba87">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse SOAP-ENC SOAP-ENV user xsd xsi" />
                     </ds:Transform>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                  <ds:DigestValue>24WiH+AtrGk4tcUVi/mj5mTEPxM=</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>ZRRjF9ejiNp8v89CgEIpPJTAn87RGL5f6/49XvdN1IfRrjbiEmYidbi0GH9Dafuh5Y1OnG5qzSg3BdCLRX3iAgciomGw7EpEg6m9SSzKZC3iwCMtLaEGdzkKHYqMkdJrb6h0PYBSYJ9JUNbYbBewt1/ksSXkChWehGMyLRspeR8=</ds:SignatureValue>
            <ds:KeyInfo Id="KI-218aa69e-2dd2-41ee-bcaa-482a8cefd64b">
               <wsse:SecurityTokenReference wsu:Id="STR-d9f5821a-36ec-4e5c-9887-2158e68ee1ff">
                  <wsse:Reference URI="#e6bac805-2ee5-4d82-8e8e-ee4c0a37e705" />
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
         <wsu:Timestamp wsu:Id="TS-15747850-9adf-4990-a5ee-8c23bb50ba87">
            <wsu:Created>2015-01-22T11:47:58.057Z</wsu:Created>
            <wsu:Expires>2015-01-22T14:47:58.057Z</wsu:Expires>
         </wsu:Timestamp>
      </wsse:Security>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body xmlns:ns="http://ejb.draco.comarch.com" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-de9cadef-6ab1-4f68-9106-b7c87ed85a95">
      <ns:getUserInfo>
         <ns:tgsId></ns:tgsId>
         <ns:appId></ns:appId>
      </ns:getUserInfo>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 

Niestety ePuap odrzucał moje zapytanie z odpowiedzią WSDoAllReceiver: security processing failed. Uruchomiłem sobie oczywiście kod w PHP z wymienionej wcześniej strony i jak to bywa on działa a obie koperty wyglądają tak samo (tzn. różnią się wartości DigestValue oraz SignatureValue i stąd wynika zapewne różnica w stosunku do Xades). Zacząłem próbować z biblioteką Xades4J na podstawie kodu z wątku Podpis Xades na pliku XML ale jak na razie bez pozytywnych rezultatów tzn. to co wygenerowałem zupełnie nie przypomina pokazanej wcześniej koperty nie mówiąc już o wartości sygnatury. Kod:

String alias = "";
            char haslo[] = "haslo".toCharArray();

            // zaladowanie pliki p12
            KeyStore store = KeyStore.getInstance("PKCS12");
            store.load(new FileInputStream("plik.p12"), haslo);

            
            // wyciagnij klucz prywatny
            Key privKey = store.getKey(alias, haslo);
            final PrivateKey privateKey = (PrivateKey) privKey;
            
            // wyciagnij certyfikat
            final X509Certificate cert = (X509Certificate) store.getCertificate(alias);

            // provider dla xades
            KeyingDataProvider keyingDataProv = new KeyingDataProvider() {

                public List<X509Certificate> getSigningCertificateChain() throws SigningCertChainException, UnexpectedJCAException {
                    return (List<X509Certificate>) (Object) Arrays.asList(cert);
                }

                public PrivateKey getSigningKey(X509Certificate signingCert) throws SigningKeyException, UnexpectedJCAException {
                    return privateKey;
                }
            };
            
            AlgorithmsProviderEx ap = new DefaultAlgorithmsProviderEx() {
                @Override
                public String getDigestAlgorithmForDataObjsReferences() {
                        return "http://www.w3.org/2000/09/xmldsig#sha1";
                }
                @Override
                public Algorithm getSignatureAlgorithm(String keyAlgorithmName)
                                throws UnsupportedAlgorithmException {
                        return new GenericAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
                }
                @Override
                public String getDigestAlgorithmForReferenceProperties() {
                        return "http://www.w3.org/2000/09/xmldsig#sha1";
                }
            };
        
            
            // plik xml do podpisania
            String inputFile = "";
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            org.w3c.dom.Document inDoc = db.parse(new FileInputStream(inputFile));

            // profil podpisu xades
            XadesSigningProfile profile = new XadesBesSigningProfile(keyingDataProv).withAlgorithmsProviderEx(ap);
            
          
            // zmienna podpisujaca
            XadesSigner signer = profile.newSigner();
            
            
            // dodatkowe dane do podpisu       
            SignedDataObjects dataObjs = new SignedDataObjects();
            DataObjectReference obj = new DataObjectReference("");    
           
            obj.withTransform(new DataObjectTransform("http://www.w3.org/2001/10/xml-exc-c14n#"));           
            dataObjs.withSignedDataObject(obj);

            // podpisanie
            signer.sign(dataObjs, inDoc.getDocumentElement());

            // Zapis podpisanego pliku
            String outputFile = "";
            OutputStream os = new FileOutputStream(outputFile);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(inDoc), new StreamResult(os));

Wynik:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:user="http://userinfo.zp.epuap.gov.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body xmlns:ns="http://ejb.draco.comarch.com" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="abcd">
      <ns:getUserInfo>
         <ns:tgsId></ns:tgsId>
         <ns:appId></ns:appId>
      </ns:getUserInfo>
   </SOAP-ENV:Body>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7">
      <ds:SignedInfo>
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
         <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
         <ds:Reference Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-ref0" URI="">
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>TI95y7S79osPz9WCiRXwptz2vmE=</ds:DigestValue>
         </ds:Reference>
         <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-signedprops">
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>2Rl17TWjQZ71k2e9vtMX1uUFxN0=</ds:DigestValue>
         </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-sigvalue">YpuextXY+k3GG+BPtlkJ97U99udTZe5z6ushOlihHcyt9LG2DobBc44C0YgyBxKVmzAe8coMzm+5
DMrFhBLVHBEx45Mka4o6jOpQoxvUQD6OM5nU8xbt1m7dZ7+3VzlilmiJVQL1kdA5R0HFbI9DrRlD
C89Y0+h0idS+vh/5gAo=</ds:SignatureValue>
      <ds:KeyInfo>
         <ds:X509Data>
            <ds:X509Certificate>MIICSjCCAbOgAwIBAgIJAIXSDNq9Dr0hMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNVBAYTAlBMMR4w
HAYDVQQKExVDUEkgQ0EgZm9yIGVwdWFwIFRFU1QxHjAcBgNVBAsTFUNQSSBDQSBmb3IgZXB1YXAg
VEVTVDEeMBwGA1UEAxMVQ1BJIENBIGZvciBlcHVhcCBURVNUMB4XDTE0MDgxNTAwMDAwMFoXDTE2
MDgxNDIzNTk1OVowRTELMAkGA1UEBhMCUEwxDDAKBgNVBAoTA0NQSTETMBEGA1UECxMKZGFtaWFu
U29mdDETMBEGA1UEAxMKZGFtaWFuU29mdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzXr0
F9mUTQ5Ow4XqwEpCEsGZKBG+OrSmqFzFpC+gC23L96gnFYVGl5Cv5vT8fMnRlb9m7ebsH7bVFL1U
sRbg4xyRi8Rf/kefSGOZmtmQG3X1BsfLsYfhXBhYC8qvjJfnm8pVaHZ1joxcUapzwTQp2Se/EFTA
odJV24JL8T8XdXcCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEF
BQADgYEAF2+pSbCJzxg0Zd75fO0zNviPvZJU6FD2aq6YQGKGghMSfBXH6M3oX6AdHWD9nXrvGCqB
6aNBdeww1RbF7qOugUYxmZ6fqxVRwADrSP81Uz8rLBQVovieCjlXdeWvXt4CGyeu1AcdXYMnsdTt
vXHHAdAoqMTP+klPAM0MrsN+GRA=</ds:X509Certificate>
         </ds:X509Data>
      </ds:KeyInfo>
      <ds:Object>
         <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#" Target="#xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7">
            <xades:SignedProperties Id="xmldsig-089c463a-9afe-480d-9e39-4e7fe1eb00e7-signedprops">
               <xades:SignedSignatureProperties>
                  <xades:SigningTime>2015-01-22T13:00:08.569+01:00</xades:SigningTime>
                  <xades:SigningCertificate>
                     <xades:Cert>
                        <xades:CertDigest>
                           <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                           <ds:DigestValue>okFqGkp1+kY2NdB8m8cQTLROKq0=</ds:DigestValue>
                        </xades:CertDigest>
                        <xades:IssuerSerial>
                           <ds:X509IssuerName>CN=CPI CA for epuap TEST,OU=CPI CA for epuap TEST,O=CPI CA for epuap TEST,C=PL</ds:X509IssuerName>
                           <ds:X509SerialNumber>9642783885767916833</ds:X509SerialNumber>
                        </xades:IssuerSerial>
                     </xades:Cert>
                  </xades:SigningCertificate>
               </xades:SignedSignatureProperties>
            </xades:SignedProperties>
         </xades:QualifyingProperties>
      </ds:Object>
   </ds:Signature>
</SOAP-ENV:Envelope>

Robię coś nie tak ale nie wiem niestety gdzie. Może ktoś przechodził już to wszystko i mógłby pomóc. Byłbym niezmiernie wdzięczny bo już powoli tracę nadzieje.

0

Sprawa już nieaktualna. Wss4j działało tylko zamiast:

builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);

należało użyć

builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
0

Obecnie też przyszło mi się borykać z problemem zbudowania poprawnej koperty SOAP dla WS Authorization. Próbuję wywołać metodę getUserInfo. Otrzymuję komunikat WSDoAllReceiver: security processing failed. Dodałem Timestamp, ale to nic nie dało. Na jaki endpoint wysyłasz kopertę SOAP? Czy otrzymujesz poprawną odpowiedź ? Czy metoda rzeczywiście zwraca wszystkie elementy, które WSDL ma w swoim schemacie? Imię, nazwisko, e-mail? Czy mógłbyś podesłać przykładową kopertę, która zwraca Ci prawidłowy wynik?

0

Witam

Nie wiem czy to jeszcze aktualne bo chyba dość późno odpowiadam. Wysyłam zapytanie na https://hetman.epuap.gov.pl/axis2/services/AuthorizationWS. W schemacie jest wszystko poprawnie zwracane o ile dostaniesz prawidłową odpowiedź. Sprawdź czy dodajesz w nagłówku BinarySecurityToken bo to akurat u mnie było nie tak. Tak na marginesie jeżeli musisz wyciągnąć naprawdę ważne dane tj. Imię Nazwisko + PESEL to jedynym i chyba najprostszym sposobem jest podpisanie dokumentu profilem zaufanym poprzez platformę ePuap. Wszystko jest dość dokładnie opisane na epuapowych stronach (no może z małymi wyjątkami).

0

Witam
Chciałbym zapytać, skąd w ogóle bierze się te Certyfikaty X905, do pola X509Certificate ?
Potrzebuję wykonać obsługę wysyłki JPK w PHP i nie mogę znaleźć jakieś odpowiedzi wprost skąd wziąć ten certyfikat ?
I wartości do innych pól xml w strukturze xades:SignedProperties ?

0

Czy komunikacja poprzez WS-SECURITY z serwerami EPUAP'u jest dostępna tylko dla podmiotów publicznych (urzędy państwowe), czy może każda firma komercyjna również ma taką możliwość ? Pytam gdyż komuś w naszej firmie wpadło do głowy, aby umożliwić klientom którzy nie mają podpisu kwalifikowanego wykonywanie wysyłki plików JPK za pomocą profilu zaufanego (podpis pliku InitUpload.xml). Czy coś takiego jest możliwe ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1