diff --git a/WS-Security Requirement and Implementation Suggestion.md b/WS-Security Requirement and Implementation Suggestion.md new file mode 100644 index 0000000..5967a68 --- /dev/null +++ b/WS-Security Requirement and Implementation Suggestion.md @@ -0,0 +1,71 @@ +# WS-Security Requirement and Implementation Suggestion + +## Overview +WS-Security adalah standar untuk mengamankan _SOAP message_ dan fungsinya adalah untuk memastikan integritas (_SOAP message_ tidak pernah diubah) dan _authenticity_ (dibuat oleh pengirim yg sebenarnya). + +## Requirement +- _Authentication Method / Token Profile_: X.509Certificate Token Profile +- _Header Attributes_: soapenv:mustUnderstand="1" harus ada di header. +- _Canonicalization_: dibutuhkan _Exclusive XML Canonicalization Omit/Without Comment_ +- _KeyIdentifier_: apa saja dari ISSUER_SERIAL, ISSUER_SERIAL_QUOTE_FORMAT, BST_DIRECT_REFERENCE, X509_KEY_IDENTIFIER, THUMBPRINT_IDENTIFIER, SKI_KEY_IDENTIFIER (dilarang pakai KEY_VALUE) (disarankan, saat ini biasa yg dipakai BST_DIRECT_REFERENCE) +- _Signature Algorithms_: apa saja dari RSA_SHA1, RSA_SHA256, RSA_SHA512 +- _Digest Algorithms_: apa saja dari SHA1, SHA256, SHA384, SHA512 +- _Signature Scope_: hanya dibutuhkan di _SOAP Body_ +- _Timestamp_: tidak dibutuhkan +- Enkripsi: jangan + +## Sample WS-Security +Ini dibuat pakai WSS4J dengan Crypto Provider Merlin dan opsi: +- SigCanonicalization: C14N_EXCL_OMIT_COMMENTS +- KeyIdentifierType: BST_DIRECT_REFERENCE +- SignatureAlgorithm: RSA_SHA1 +- DigestAlgo: SHA256 + +```xml + + + + + MII...base64-cert... + + + + + + + + + + + + U2VsYW1hdC4uLiBBbmRhIG1lbmVtdWthbiBzYXlh4nE= + + + SGVsbG8gdGhlcmUuIEhvdydzIGxpZmU/IC0tc2tyYW1kNGogZGV2ZWxvcGVyy7+RjD9xM1naWNTuekorKgW4f5UTcLhFGPh81RqrXvbsWspjqUMLCS/7xQU1ipQLjVFfAG+S2/72S9OiILhz9ei6hIIJCodkf96PmaldSSNgKgw= + + + + + + + + + + Meow kucing + + +``` + +# Implementation Suggestion +Pakai ini (atau yg lebih baik, yg disupport): +- SigCanonicalization: C14N_EXCL_OMIT_COMMENTS +- KeyIdentifierType: BST_DIRECT_REFERENCE +- SignatureAlgorithm: RSA_SHA256 +- DigestAlgo: SHA256 + +Lihat [sign example](./sign-example). + +## Caveats +- **Pastikan Body dan SignedInfo tidak berubah setelah proses signing**. Proses signing mengunci keaslian data dengan cara membubuhkan bukti hashing kriptografi untuk mendeteksi adanya perubahan. Jadikan proses signing hal yg sangat terakhir dari _workflow_ anda. Silahkan atur data sesuai keinginan namun jangan ubah sama sekali setelah proses signing. (beda spasi saja akan merusak signing). +- **Disarankan gunakan [implementation suggestion](#implementation-suggestion)** apabila bingung. +- **_Selftest_ terlebih dahulu jika ingin memastikan**. Sign data anda lalu verify secara mandiri. \ No newline at end of file diff --git a/com-example-wssecurity/.gitignore b/com-example-wssecurity/.gitignore new file mode 100644 index 0000000..18cfb6c --- /dev/null +++ b/com-example-wssecurity/.gitignore @@ -0,0 +1,21 @@ +## https://github.com/github/gitignore/blob/main/Maven.gitignore +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://maven.apache.org/wrapper/#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +## custom +.vscode \ No newline at end of file diff --git a/com-example-wssecurity/pom.xml b/com-example-wssecurity/pom.xml new file mode 100644 index 0000000..5d77bb1 --- /dev/null +++ b/com-example-wssecurity/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + com.example + wssecurity + 1.0-SNAPSHOT + + + 1.8 + + + + + + org.apache.wss4j + wss4j-ws-security-dom + 2.4.3 + + + + \ No newline at end of file diff --git a/com-example-wssecurity/src/main/java/com/example/ExampleWsSecurity.java b/com-example-wssecurity/src/main/java/com/example/ExampleWsSecurity.java new file mode 100644 index 0000000..53f8066 --- /dev/null +++ b/com-example-wssecurity/src/main/java/com/example/ExampleWsSecurity.java @@ -0,0 +1,60 @@ +package com.example; + +import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.dom.message.WSSecHeader; +import org.apache.wss4j.dom.message.WSSecSignature; +import org.apache.wss4j.common.crypto.Crypto; +import org.apache.wss4j.common.crypto.CryptoFactory; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; + +public class ExampleWsSecurity { + public static void main(String[] args) throws Exception { + // Simple SOAP envelope + String soap = "" + + "\n" + + "\n" + + " Meow kucing\n" + + "\n" + + ""; + + // Parse SOAP to DOM + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + Document doc = dbf.newDocumentBuilder() + .parse(new ByteArrayInputStream(soap.getBytes(StandardCharsets.UTF_8))); + + // Load crypto from properties (assumes crypto.properties in classpath) + Crypto crypto = CryptoFactory.getInstance("crypto.properties"); + + // Insert WS-Security header + WSSecHeader secHeader = new WSSecHeader(doc); + secHeader.insertSecurityHeader(); + + // Sign SOAP Body only + WSSecSignature signature = new WSSecSignature(secHeader); + signature.setUserInfo("wsstest", "changeit"); // alias and password + signature.setSigCanonicalization(WSConstants.C14N_EXCL_OMIT_COMMENTS); + signature.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); + signature.setSignatureAlgorithm(WSConstants.RSA_SHA256); + signature.setDigestAlgo(WSConstants.SHA256); + + Document signedDoc = signature.build(crypto); + + // Print signed SOAP message + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + + StringWriter sw = new StringWriter(); + transformer.transform(new DOMSource(signedDoc), new StreamResult(sw)); + System.out.println(sw.toString()); + } +} diff --git a/com-example-wssecurity/src/main/resources/crypto.properties b/com-example-wssecurity/src/main/resources/crypto.properties new file mode 100644 index 0000000..61a3d94 --- /dev/null +++ b/com-example-wssecurity/src/main/resources/crypto.properties @@ -0,0 +1,4 @@ +org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin +org.apache.wss4j.crypto.merlin.keystore.type=jks +org.apache.wss4j.crypto.merlin.keystore.password=changeit +org.apache.wss4j.crypto.merlin.keystore.file=store.jks