add wss requirement and suggestion

This commit is contained in:
Hizbu Azka 2025-12-07 12:59:11 +07:00
parent eb82c22efe
commit 883a70fc5a
5 changed files with 179 additions and 0 deletions

@ -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 <wsse:Security> 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
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv: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" soapenv:mustUnderstand="1">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-33adc7a9-743b-4acd-ac3d-7947b5728d8b">MII...base64-cert...</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-e3b862f3-c19b-43a8-bdd2-3aa53cb306eb">
<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="soapenv"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-e4e057db-4f7f-4c44-aae6-ffb3607ba5fd">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>U2VsYW1hdC4uLiBBbmRhIG1lbmVtdWthbiBzYXlh4nE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>SGVsbG8gdGhlcmUuIEhvdydzIGxpZmU/IC0tc2tyYW1kNGogZGV2ZWxvcGVyy7+RjD9xM1naWNTuekorKgW4f5UTcLhFGPh81RqrXvbsWspjqUMLCS/7xQU1ipQLjVFfAG+S2/72S9OiILhz9ei6hIIJCodkf96PmaldSSNgKgw=</ds:SignatureValue>
<ds:KeyInfo Id="KI-3336434d-1994-4afc-9b9b-5df2de3b8761">
<wsse:SecurityTokenReference wsu:Id="STR-606e4c7b-1e9d-42a8-bbd1-d426c22afb45">
<wsse:Reference URI="#X509-33adc7a9-743b-4acd-ac3d-7947b5728d8b" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-e4e057db-4f7f-4c44-aae6-ffb3607ba5fd">
Meow kucing
</soapenv:Body>
</soapenv:Envelope>
```
# 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.

21
com-example-wssecurity/.gitignore vendored Normal file

@ -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

@ -0,0 +1,23 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>wssecurity</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.wss4j/wss4j-ws-security-dom -->
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-dom</artifactId>
<version>2.4.3</version>
</dependency>
</dependencies>
</project>

@ -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 = "" +
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
"<soapenv:Body>\n" +
" Meow kucing\n" +
"</soapenv:Body>\n" +
"</soapenv:Envelope>";
// 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());
}
}

@ -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