Skip to content

Commit 4afa14f

Browse files
authored
Merge pull request #165 from CyberSource/future
Future
2 parents 202346b + f487d4b commit 4afa14f

File tree

11 files changed

+179
-122
lines changed

11 files changed

+179
-122
lines changed

README.md

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CyberSource Simple Order API for Java
22

3-
[![Build Status](https://travis-ci.org/CyberSource/cybersource-sdk-java.png?branch=master)](https://travis-ci.org/CyberSource/cybersource-sdk-java)
3+
[![Build Status](https://travis-ci.org/CyberSource/cybersource-sdk-java.png?branch=future)](https://travis-ci.org/CyberSource/cybersource-sdk-java)
44

55
## Package Managers
66

@@ -10,7 +10,7 @@ To install the `cybersource-sdk-java` from central repository, add dependency to
1010
<dependency>
1111
<groupId>com.cybersource</groupId>
1212
<artifactId>cybersource-sdk-java</artifactId>
13-
<version>6.2.11</version>
13+
<version>6.2.12</version>
1414
</dependency>
1515
```
1616
Run `mvn install` to install dependency
@@ -19,7 +19,7 @@ Run `mvn install` to install dependency
1919
Add the dependency to your build.gradle
2020
```java
2121
dependencies {
22-
compile 'com.cybersource:cybersource-sdk-java:6.2.11'
22+
compile 'com.cybersource:cybersource-sdk-java:6.2.12'
2323
}
2424
```
2525
## Requirements
@@ -227,29 +227,38 @@ Retry Pattern allows to retry sending a failed request and it will only work wit
227227
- Config parameter for this property is 'retryInterval' in `cybs.property` file. The default value for 'retryInterval' parameter is 1000 which means a delay of 1000 milliSeconds.
228228

229229
## Third Party jars
230-
1. org.apache.ws.security.wss4j:1.6.19
231-
The Apache WSS4J project provides a Java implementation of the primary security standards for Web Services, namely the OASIS Web Services Security (WS-Security) specifications from the OASIS Web Services Security TC.
232-
2. org.bouncycastle:bcprov-jdk15on:1.61
230+
1. org.apache.wss4j:wss4j-ws-security-common:2.4.1
231+
The Apache WSS4J project provides a Java implementation of the common primary security standards for Web Services, namely the OASIS Web Services Security (WS-Security) specifications from the OASIS Web Services Security TC.
232+
2. org.apache.wss4j:wss4j-ws-security-dom:2.4.1
233+
WSS4J 2.0.0 introduces a streaming (StAX-based) WS-Security implementation to complement the existing DOM-based implementation. The DOM-based implementation is quite performant and flexible, but suffers from having to read the entire XML tree into memory. For large SOAP requests this can have a detrimental impact on performance. In addition, for web services stacks such as Apache CXF which are streaming-based, it carries an additional performance penalty of having to explicitly convert the request stream to a DOM Element.
234+
3. org.bouncycastle:bcprov-jdk15on:1.70
233235
This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.5 to JDK 1.8.
234-
3. org.apache.santuario:xmlsec:1.5.6
236+
4. org.apache.santuario:xmlsec:2.3.0
235237
The XML Security project is aimed at providing implementation of security standards for XML,supports XML-Signature Syntax and Processing,XML Encryption Syntax and Processing, and supports XML Digital Signature APIs.
236-
4. org.apache.commons:commons-lang3:3.4
238+
5. org.apache.commons:commons-lang3:3.4
237239
Apache Commons Lang, a package of Java utility classes for the classes that are in java.lang's hierarchy, or are considered to be so standard as to justify existence in java.lang.
238-
5. commons-logging:commons-logging:jar:1.1.1
240+
6. commons-logging:commons-logging:jar:1.1.1
239241
This is getting downloaded as compile time dependency of wss4j:1.6.19.Apache Commons Logging is a thin adapter allowing configurable bridging to other, well known logging systems.
240-
6. org.slf4j:slf4j-api:1.7.21 and org.slf4j:slf4j-jcl:1.7.21
242+
7. org.slf4j:slf4j-api:1.7.32 and org.slf4j:slf4j-jcl:1.7.32
241243
slf4j-api is getting used as a dependency for wss4j. Modified to latest version.
242-
7. junit:junit:4.13.1
244+
8. junit:junit:4.13.1
243245
JUnit is a unit testing framework for Java.
244-
8. org.mockito:mockito-all:1.10.19
246+
9. org.mockito:mockito-all:1.10.19
245247
Mock objects library for java
246-
9. org.apache.httpcomponents:httpclient:4.5.13
248+
10. org.apache.httpcomponents:httpclient:4.5.13
247249
Provides reusable components for client-side authentication, HTTP state management, and HTTP connection management. It is used for poolinghttpclientconnectionmanager feature.
248-
10. org.apache.httpcomponents:httpcore:4.4.13
250+
11. org.apache.httpcomponents:httpcore:4.4.13
249251
Provides low level HTTP transport components that can be used to build custom client and server side HTTP services with a minimal footprint.
250252

251253
## Changes
252254
_______________________________
255+
Version Cybersource-sdk-java 6.2.12 (JUNE,2022)
256+
_______________________________
257+
1) Mitigation of Apache WSS4j Security Vulnerability (CVE-2016-1000343, CVE-2018-1000180).
258+
i) Updated Apache wss4j version from 1.6.19 to 2.4.1
259+
ii) Updated dependent libraries version. (xmlsec from 1.5.6 to 2.3.0, bcprov-jdk15on from 1.61 to 1.70)
260+
_______________________________
261+
_______________________________
253262
Version Cybersource-sdk-java 6.2.11 (MAY,2020)
254263
_______________________________
255264
1)Exception handling improvement.

java/pom.xml

+30-20
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22
<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/maven-v4_0_0.xsd">
33

44
<modelVersion>4.0.0</modelVersion>
5+
56
<parent>
6-
<groupId>org.sonatype.oss</groupId>
7-
<artifactId>oss-parent</artifactId>
8-
<version>7</version>
7+
<artifactId>cybersource-sdk-master</artifactId>
8+
<groupId>com.cybersource</groupId>
9+
<version>6.2.12-SNAPSHOT</version>
910
</parent>
11+
1012
<groupId>com.cybersource</groupId>
1113
<artifactId>cybersource-sdk-java</artifactId>
1214
<version>6.2.12-SNAPSHOT</version>
1315
<name>cybersource-sdk-java</name>
1416
<description>Simple Order API Client</description>
1517
<url>http://www.cybersource.com</url>
18+
1619
<licenses>
1720
<license>
1821
<name>CyberSource SDK License Agreement</name>
@@ -34,10 +37,6 @@
3437
</developer>
3538
</developers>
3639

37-
<properties>
38-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
39-
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
40-
</properties>
4140
<packaging>jar</packaging>
4241

4342
<profiles>
@@ -219,23 +218,23 @@
219218
<dependency>
220219
<groupId>junit</groupId>
221220
<artifactId>junit</artifactId>
222-
<version>4.13.1</version>
221+
<version>${junit.version}</version>
223222
<scope>test</scope>
224223
</dependency>
225224
<dependency>
226225
<groupId>xalan</groupId>
227226
<artifactId>xalan</artifactId>
228-
<version>2.7.2</version>
227+
<version>${xalan.version}</version>
229228
</dependency>
230229
<dependency>
231230
<groupId>org.apache.santuario</groupId>
232231
<artifactId>xmlsec</artifactId>
233-
<version>1.5.6</version>
232+
<version>${xmlsec.version}</version>
234233
</dependency>
235234
<dependency>
236235
<groupId>org.apache.httpcomponents</groupId>
237236
<artifactId>httpclient</artifactId>
238-
<version>4.5.13</version>
237+
<version>${httpclient.version}</version>
239238
<exclusions>
240239
<exclusion>
241240
<groupId>commons-logging</groupId>
@@ -246,28 +245,39 @@
246245
<dependency>
247246
<groupId>org.bouncycastle</groupId>
248247
<artifactId>bcprov-jdk15on</artifactId>
249-
<version>1.61</version>
248+
<version>${bouncycastle.version}</version>
249+
</dependency>
250+
<dependency>
251+
<groupId>org.apache.wss4j</groupId>
252+
<artifactId>wss4j-ws-security-common</artifactId>
253+
<version>${wss4j.version}</version>
254+
<exclusions>
255+
<exclusion>
256+
<groupId>com.google.guava</groupId>
257+
<artifactId>guava</artifactId>
258+
</exclusion>
259+
</exclusions>
250260
</dependency>
251261
<dependency>
252-
<groupId>org.apache.ws.security</groupId>
253-
<artifactId>wss4j</artifactId>
254-
<version>1.6.19</version>
255-
<exclusions>
262+
<groupId>org.apache.wss4j</groupId>
263+
<artifactId>wss4j-ws-security-dom</artifactId>
264+
<version>${wss4j.version}</version>
265+
<exclusions>
256266
<exclusion>
257-
<groupId>org.opensaml</groupId>
258-
<artifactId>opensaml</artifactId>
267+
<groupId>org.ehcache</groupId>
268+
<artifactId>ehcache</artifactId>
259269
</exclusion>
260270
</exclusions>
261271
</dependency>
262272
<dependency>
263273
<groupId>org.apache.commons</groupId>
264274
<artifactId>commons-lang3</artifactId>
265-
<version>3.4</version>
275+
<version>${commonlang3.version}</version>
266276
</dependency>
267277
<dependency>
268278
<groupId>org.mockito</groupId>
269279
<artifactId>mockito-all</artifactId>
270-
<version>1.10.19</version>
280+
<version>${mockito.version}</version>
271281
<scope>test</scope>
272282
</dependency>
273283
</dependencies>

java/src/main/java/com/cybersource/ws/client/Identity.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private void setupJdkServerCerts() throws SignException {
7272
}
7373
else if (subjectDNrray.length == 2 && subjectDNrray[1].contains(SERVER_ALIAS)) {
7474
name = SERVER_ALIAS;
75-
serialNumber = subjectDNrray[1];
75+
serialNumber = subjectDNrray[1].split(",")[0];
7676
keyAlias = "serialNumber=" + serialNumber + ",CN=" + name;
7777
}else{
7878
throw new SignException("Exception while obtaining private key from KeyStore with alias, '" + merchantConfig.getKeyAlias() + "'");

java/src/main/java/com/cybersource/ws/client/MessageHandlerKeyStore.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.cybersource.ws.client;
22

3-
import org.apache.ws.security.components.crypto.CredentialException;
4-
import org.apache.ws.security.components.crypto.Merlin;
3+
import org.apache.wss4j.common.crypto.Merlin;
54

65
import java.io.IOException;
76
import java.security.KeyStoreException;
@@ -15,11 +14,10 @@
1514
public class MessageHandlerKeyStore extends Merlin {
1615

1716
/**
18-
* @throws CredentialException
1917
* @throws IOException
2018
*/
21-
public MessageHandlerKeyStore() throws CredentialException, IOException {
22-
super(null);
19+
public MessageHandlerKeyStore() {
20+
super();
2321
properties = new Properties();
2422
}
2523

java/src/main/java/com/cybersource/ws/client/SecurityUtil.java

+42-38
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
package com.cybersource.ws.client;
22

3-
import org.apache.ws.security.WSConstants;
4-
import org.apache.ws.security.WSEncryptionPart;
5-
import org.apache.ws.security.WSSecurityException;
6-
import org.apache.ws.security.components.crypto.CredentialException;
7-
import org.apache.ws.security.message.WSSecEncrypt;
8-
import org.apache.ws.security.message.WSSecHeader;
9-
import org.apache.ws.security.message.WSSecSignature;
3+
import org.apache.wss4j.common.WSEncryptionPart;
4+
import org.apache.wss4j.common.ext.WSSecurityException;
5+
import org.apache.wss4j.common.util.KeyUtils;
6+
import org.apache.wss4j.dom.WSConstants;
7+
import org.apache.wss4j.dom.WSDocInfo;
8+
import org.apache.wss4j.dom.message.WSSecEncrypt;
9+
import org.apache.wss4j.dom.message.WSSecHeader;
10+
import org.apache.wss4j.dom.message.WSSecSignature;
11+
import org.apache.xml.security.Init;
1012
import org.bouncycastle.jce.provider.BouncyCastleProvider;
1113
import org.w3c.dom.Document;
1214

15+
import javax.crypto.KeyGenerator;
1316
import java.io.FileInputStream;
1417
import java.io.FileNotFoundException;
1518
import java.io.IOException;
1619
import java.security.*;
17-
import java.security.cert.Certificate;
1820
import java.security.cert.CertificateException;
1921
import java.security.cert.X509Certificate;
2022
import java.util.Collections;
@@ -44,20 +46,22 @@ public class SecurityUtil {
4446
private static final String SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
4547
// By default digest algorithm is set to "http://www.w3.org/2000/09/xmldsig#sha1"
4648
private static final String DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmlenc#sha256";
47-
49+
4850
private static BouncyCastleProvider bcProvider = new BouncyCastleProvider();
4951

5052
// This is loaded by WSS4J but since we use it lets make sure its here
5153
static {
5254
Security.addProvider(bcProvider);
5355
try {
5456
initKeystore();
57+
//Must initialize xml-security library correctly before use it
58+
Init.init();
5559
} catch (Exception e) {
5660
localKeyStoreHandler=null;
5761
}
5862
}
5963

60-
private static void initKeystore() throws KeyStoreException, CredentialException, IOException, NoSuchAlgorithmException, CertificateException{
64+
private static void initKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException{
6165
KeyStore keyStore = KeyStore.getInstance("jks");
6266
keyStore.load(null, null);
6367
localKeyStoreHandler = new MessageHandlerKeyStore();
@@ -190,50 +194,50 @@ private static void readAndStoreCertificateAndPrivateKey(MerchantConfig merchant
190194
* @throws SignException
191195
*/
192196
public static Document handleMessageCreation(Document signedDoc, String merchantId, Logger logger) throws SignEncryptException, SignException{
193-
197+
194198
logger.log(Logger.LT_INFO, "Encrypting Signed doc ...");
195-
196-
WSSecHeader secHeader = new WSSecHeader();
199+
200+
WSSecHeader secHeader = new WSSecHeader(signedDoc);
197201
try {
198-
secHeader.insertSecurityHeader(signedDoc);
202+
secHeader.insertSecurityHeader();
199203
} catch (WSSecurityException e) {
200204
logger.log(Logger.LT_EXCEPTION, "Exception while adding document in soap securiy header for MLE");
201205
throw new SignException(e);
202206
}
203-
204-
WSSecEncrypt encrBuilder = new WSSecEncrypt();
207+
208+
WSSecEncrypt encrBuilder = new WSSecEncrypt(secHeader);
205209
//Set the user name to get the encryption certificate.
206210
//The public key of this certificate is used, thus no password necessary. The user name is a keystore alias usually.
207211
encrBuilder.setUserInfo(identities.get(SERVER_ALIAS).getKeyAlias());
208-
212+
209213
/*This is to reference a public key or certificate when signing or encrypting a SOAP message.
210214
*The following valid values for these configuration items are:
211215
*IssuerSerial (default),DirectReference[BST],X509KeyIdentifier,Thumbprint,SKIKeyIdentifier,KeyValue (signature only),EncryptedKeySHA1 (encryption only)
212216
*/
213217
encrBuilder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
214-
218+
215219
//This encryption algorithm is used to encrypt the data.
216220
encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_256);
217-
221+
218222
//Sets the algorithm to encode the symmetric key. Default is the WSConstants.KEYTRANSPORT_RSAOEP algorithm.
219223
//encrBuilder.setKeyEnc(WSConstants.KEYTRANSPORT_RSAOEP);
220-
221-
224+
222225
//Create signed document
223226
//Document signedDoc = createSignedDoc(workingDocument,senderAlias,password,secHeader);
224-
227+
225228
Document signedEncryptedDoc;
226229
try {
227230
//Builds the SOAP envelope with encrypted Body and adds encrypted key.
228231
// If no external key (symmetricalKey) was set ,generate an encryption
229232
// key (session key) for this Encrypt element. This key will be
230233
// encrypted using the public key of the receiver
231-
signedEncryptedDoc = encrBuilder.build(signedDoc, localKeyStoreHandler, secHeader);
234+
KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_256);
235+
signedEncryptedDoc = encrBuilder.build(localKeyStoreHandler, keyGen.generateKey());
232236
} catch (WSSecurityException e) {
233237
logger.log(Logger.LT_EXCEPTION, "Failed while encrypting signed requeest for , '" + merchantId + "'" + " with " + SERVER_ALIAS);
234238
throw new SignEncryptException("Failed while encrypting signed requeest for , '" + merchantId + "'" + " with " + SERVER_ALIAS, e);
235239
}
236-
encrBuilder.prependToHeader(secHeader);
240+
encrBuilder.prependToHeader();
237241
return signedEncryptedDoc;
238242
}
239243

@@ -247,34 +251,34 @@ public static Document handleMessageCreation(Document signedDoc, String merchant
247251
* @throws SignException
248252
*/
249253
public static Document createSignedDoc(Document workingDocument,String keyAlias, String password,Logger logger) throws SignException {
250-
251254
logger.log(Logger.LT_INFO, "Signing request...");
252-
//long startTime = System.nanoTime();
253-
WSSecHeader secHeader = new WSSecHeader();
255+
// long startTime = System.nanoTime();
256+
WSSecHeader secHeader = new WSSecHeader(workingDocument);
254257
try {
255-
secHeader.insertSecurityHeader(workingDocument);
258+
secHeader.insertSecurityHeader();
256259
} catch (WSSecurityException e) {
257260
logger.log(Logger.LT_EXCEPTION,
258-
"Exception while signing XML document");
261+
"Exception while signing XML document");
259262
throw new SignException(e);
260263
}
261-
262-
WSSecSignature sign = new WSSecSignature();
263-
264+
265+
WSSecSignature sign = new WSSecSignature(secHeader);
264266
sign.setUserInfo(keyAlias, password);
265-
266-
//sign.setUserInfo(mc.getKeyAlias(), mc.getPassword());
267+
267268
sign.setDigestAlgo(DIGEST_ALGORITHM);
268269
sign.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
269270
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
270271
sign.setUseSingleCertificate(true);
271-
272+
//
273+
sign.setWsDocInfo(new WSDocInfo(workingDocument));
274+
272275
//Set which parts of the message to encrypt/sign.
273276
WSEncryptionPart msgBodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "");
274-
sign.setParts(Collections.singletonList(msgBodyPart));
277+
275278
try {
276-
Document document = sign.build(workingDocument, localKeyStoreHandler, secHeader);
277-
//System.out.println("SecurityUtil.createSignedDoc time taken to sign the request is " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
279+
sign.addReferencesToSign(Collections.singletonList(msgBodyPart));
280+
Document document = sign.build(localKeyStoreHandler);
281+
// System.out.println("SecurityUtil.createSignedDoc time taken to sign the request is " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
278282
return document;
279283
} catch (WSSecurityException e) {
280284
logger.log(Logger.LT_EXCEPTION, "Failed while signing request for , '" + keyAlias + "'");

0 commit comments

Comments
 (0)