Adding InclusiveNamespaces with WSS4J - wss4j

In a WS-Security header, I'd like to add InclusiveNamespaces like this but I do not know how:
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="wsse oas soapenv urn urn1 urn2 urn3 urn4" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
Here is my code that creates the security header, how do I add the InclusiveNamespaces with WSS4J as seen in above XML snippet?
public static SOAPMessage signSoapMessage(SOAPMessage message,
String keystorePassword, String irsPrivateKeyPassword,
char[] passphrase) throws WSSecurityException {
PrivateKeyEntry privateKeyEntry = getPrivateKeyEntry(keystorePassword,
irsPrivateKeyPassword);
PrivateKey signingKey = privateKeyEntry.getPrivateKey();
X509Certificate signingCert = (X509Certificate) privateKeyEntry
.getCertificate();
final String alias = "signingKey";
final int signatureValidityTime = 3600; // 1hour in seconds
WSSConfig config = new WSSConfig();
config.setWsiBSPCompliant(false);
WSSecSignature builder = new WSSecSignature(config);
builder.setX509Certificate(signingCert);
builder.setUserInfo(alias, new String(passphrase));
builder.setUseSingleCertificate(true);
builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
builder.setDigestAlgo(WSConstants.SHA1);
builder.setSignatureAlgorithm(WSConstants.RSA_SHA1);
builder.setSigCanonicalization(WSConstants.C14N_EXCL_WITH_COMMENTS);
try {
Document document = toDocument(message);
WSSecHeader secHeader = new WSSecHeader();
//secHeader.setMustUnderstand(true);
secHeader.insertSecurityHeader(document);
WSSecTimestamp timestamp = new WSSecTimestamp();
timestamp.setTimeToLive(signatureValidityTime);
document = timestamp.build(document, secHeader);
List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp",
WSConstants.WSU_NS, "");
WSEncryptionPart aCATransmitterManifestReqDtlPart = new WSEncryptionPart(
"ACATransmitterManifestReqDtl",
"urn:us:gov:treasury:irs:ext:aca:air:7.0", "");
WSEncryptionPart aCABusinessHeaderPart = new WSEncryptionPart(
"ACABusinessHeader",
"urn:us:gov:treasury:irs:msg:acabusinessheader", "");
parts.add(timestampPart);
parts.add(aCATransmitterManifestReqDtlPart);
parts.add(aCABusinessHeaderPart);
builder.setParts(parts);
Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
Crypto crypto = CryptoFactory.getInstance(properties);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null, passphrase);
keystore.setKeyEntry(alias, signingKey, passphrase,
new Certificate[] { signingCert });
((Merlin) crypto).setKeyStore(keystore);
crypto.loadCertificate(new ByteArrayInputStream(signingCert
.getEncoded()));
document = builder.build(document, crypto, secHeader);
updateSOAPMessage(document, message);
} catch (Exception e) {
// throw new
// WSSecurityException(WSSecurityException.Reason.SIGNING_ISSUE, e);
e.printStackTrace();
}
return message;
}
private static Document toDocument(SOAPMessage soapMsg)
throws TransformerConfigurationException, TransformerException,
SOAPException, IOException {
Source src = soapMsg.getSOAPPart().getContent();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(src, result);
return (Document) result.getNode();
}
//https://svn.apache.org/repos/asf/webservices/wss4j/branches/WSS4J_1_1_0_FINAL/test/wssec/SOAPUtil.java
private static SOAPMessage updateSOAPMessage(Document doc,
SOAPMessage message)
throws Exception {
DOMSource domSource = new DOMSource(doc);
message.getSOAPPart().setContent(domSource);
return message;
}
EDIT WITH ANSWER
The above code is for v1.6.x of WSS4J and so the solution to above code is
WSSConfig config = new WSSConfig();
config.setWsiBSPCompliant(true);

Related

Export entities to database schema through java code

A long time ago, I did that with a code like that:
Configuration config = new Configuration();
Properties props = new Properties();
FileInputStream fos = = new FileInputStream( file_name );
props.load(fos);
fos.close();
config.setProperties(props);
config.addAnnotatedClass(...);
Connection conn = DriverManager.getConnection(url,usuario,senha);
SchemaExport schema = new SchemaExport();
schema.create(true, true);
But now, if I try use this code, I got a compilation error. Seeing the javadoc for SchemaExport, I notice a lot of changes in the methods used on this example.
Hpw I could do that now?
update
based on the suggested link, I implemented the method this way:
public void criarTabelas(String server, String user, String pass) throws Exception {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().applySetting("hibernate.hbm2ddl.auto", "create").applySetting("hibernate.dialect", dialect).applySetting("hibernate.id.new_generator_mappings", "true").build();
MetadataSources sources = new MetadataSources(standardRegistry);
for(Class<?> entity : lista_entidades())
sources.addAnnotatedClass(entity);
MetadataImplementor metadata = (MetadataImplementor) sources.getMetadataBuilder().build();
SchemaExport export = new SchemaExport();
export.create(EnumSet.of(TargetType.DATABASE), metadata);
}
private List<Class<?>> lista_entidades() throws Exception {
List<Class<?>> lista = new ArrayList<Class<?>>();
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
for (BeanDefinition bd : scanner.findCandidateComponents("org.loja.model"))
lista.add(Class.forName(bd.getBeanClassName()));
return lista;
}
Now I need a way to establish a jdbc connection and associate to the SchemaExport.
I solve this issue with this code:
public void criarTabelas(String server, String user, String pass) throws Exception {
Connection conn = DriverManager.getConnection(url_prefix+server+"/"+url_suffix, user, pass);
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.applySetting("hibernate.hbm2ddl.auto", "create")
.applySetting("hibernate.dialect", dialect)
.applySetting("hibernate.id.new_generator_mappings", "true")
.applySetting("javax.persistence.schema-generation-connection", conn)
.build();
MetadataSources sources = new MetadataSources(standardRegistry);
for(Class<?> entity : lista_entidades())
sources.addAnnotatedClass(entity);
MetadataImplementor metadata = (MetadataImplementor) sources.getMetadataBuilder().build();
SchemaExport export = new SchemaExport();
export.create(EnumSet.of(TargetType.DATABASE), metadata);
conn.close();
}
private List<Class<?>> lista_entidades() throws Exception {
List<Class<?>> lista = new ArrayList<Class<?>>();
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
for (BeanDefinition bd : scanner.findCandidateComponents("org.loja.model"))
lista.add(Class.forName(bd.getBeanClassName()));
System.out.println("lista: "+lista);
return lista;
}

Client side code for multipart REST operation

Hi I need to consume a REST operation which accepts a xml payload and a pdf file. Basically a JAXB object is converted to xml string and uploaded in a xml file. So in a multipart request, a xml file and pdf file are uploaded.
The REST operation server side code is as follows:
server side:
public class CompanyType extends MediaType {
public final static final XML_STRING = "applicaiton/company+xml";
}
#POST
#Path("/upload")
#Consumes("multipart/mixed")
#Produces(CompanyType.XML_STRING)
public UploadResponseObject upload(MultiPart multiPart){
UploadRequestObject req = multiPart.getBodyParts().get(0).getEntityAs(UploadRequestObject.class);
BodyPartEntity bpe = (BodyPartEntity) multiPart.getBodyParts().get(1).getEntity();
byte[] pdfBytes = IOUtils.toByteArray(bpe.getInputStream());
....
....
}
client side code to consume REST operation:
#Autowired
private RestTemplate rt;
public UploadResponseObject callMultipartUploadOperation(UploadRequestObject req, java.io.File target) throws Exception {
String url = "http://<host-name>:<port>/service-name/upload");
MultiValueMap<String, Object> mv = new LinkedMultiValueMap<String, Object>();
this.rt = new RestTemplate();
this.rt.setMessageConverters(getMessageConverter());
String id = <random number generated from 1 to 50000>;
// Add xml entity
org.springframework.http.HttpHeaders xmlFileHeaders = new org.springframework.http.HttpHeaders();
xmlFileHeaders.add(MeditType.CONTENT_TYPE, "applicaiton/company+xml");
HttpEntity<String> xmlFile = new HttpEntity<String>(createXMLString(req), xmlFileHeaders);
mv.add(id + ".xml", xmlFile);
// Add pdf file
org.springframework.http.HttpHeaders fileHeaders = new org.springframework.http.HttpHeaders();
fileHeaders.add(MediaType.CONTENT_TYPE, "application/pdf");
FileSystemResource fsr = new FileSystemResource(target);
HttpEntity<FileSystemResource> fileEntity = new HttpEntity<FileSystemResource>(
fsr, fileHeaders);
String filename = target.getName();
mv.add(filename, fileEntity);
HttpEntity<UploadRequestObject> ereq = new HttpEntity<UploadRequestObject>(req, getRequestHeaders());
ResponseEntity<UploadResponseObject> res= this.restTemplate.postForEntity(url, ereq, UploadResponseObject.class);
return res.getBody();
}
private List<HttpMessageConverter<?>> getMessageConverter() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setClassesToBeBound(UploadResponseObject.class);
MarshallingHttpMessageConverter mhmc = new MarshallingHttpMessageConverter(jaxb2Marshaller);
List<org.springframework.http.MediaType> supportedMediaTypes = new ArrayList<org.springframework.http.MediaType>();
supportedMediaTypes.add(new org.springframework.http.MediaType("application", "company+xml"));
mhmc.setSupportedMediaTypes(supportedMediaTypes);
messageConverters.add(mhmc);
// Add Form and Part converters
FormHttpMessageConverter fmc = new FormHttpMessageConverter();
fmc.addPartConverter(new Jaxb2RootElementHttpMessageConverter());
messageConverters.add(fmc);
return messageConverters;
}
When the below line is executed from client code,
ResponseEntity<UploadResponseObject> res= this.rt.postForEntity(url, ereq, UploadResponseObject.class);
the following exception is thrown
org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter
found for request
type [org..types.UploadRequestObject]
and content type [application/company+xml]
Please advise the changes to make the client side code work.
After much trial and error, was able to find the solution for the same.
Client side code:
#Autowired
private RestTemplate rt;
public UploadResponseObject callMultipartUploadOperation(UploadRequestObject req, java.io.File target) throws Exception {
String url = "http://<host-name>:<port>/service-name/upload");
MultiValueMap<String, Object> mv = new LinkedMultiValueMap<String, Object>();
this.rt = new RestTemplate();
this.rt.setMessageConverters(getMessageConverter());
String id = <random number generated from 1 to 50000>;
// Add xml entity
org.springframework.http.HttpHeaders xmlFileHeaders = new org.springframework.http.HttpHeaders();
xmlFileHeaders.add(MeditType.CONTENT_TYPE, "applicaiton/company+xml");
HttpEntity<String> xmlFile = new HttpEntity<String>(createXMLString(req), xmlFileHeaders);
mv.add(id + ".xml", xmlFile);
// Add pdf file
org.springframework.http.HttpHeaders fileHeaders = new org.springframework.http.HttpHeaders();
fileHeaders.add(MediaType.CONTENT_TYPE, "application/pdf");
FileSystemResource fsr = new FileSystemResource(target);
HttpEntity<FileSystemResource> fileEntity = new HttpEntity<FileSystemResource>(
fsr, fileHeaders);
String filename = target.getName();
mv.add(filename, fileEntity);
HttpEntity<UploadRequestObject> ereq = new HttpEntity<UploadRequestObject>(req, getRequestHeaders());
ResponseEntity<UploadResponseObject> res= this.restTemplate.postForEntity(url, ereq, UploadResponseObject.class);
return res.getBody();
}
Message converters:
private List<HttpMessageConverter<?>> getMessageConverter() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setClassesToBeBound(UploadResponseObject.class);
MarshallingHttpMessageConverter mhmc = new MarshallingHttpMessageConverter(jaxb2Marshaller);
List<org.springframework.http.MediaType> supportedMediaTypes = new ArrayList<org.springframework.http.MediaType>();
supportedMediaTypes.add(new org.springframework.http.MediaType("application", "company+xml"));
supportedMediaTypes.add(new org.springframework.http.MediaType("multipart", "form-data"));
mhmc.setSupportedMediaTypes(supportedMediaTypes);
messageConverters.add(mhmc);
// Add Form and Part converters
FormHttpMessageConverter fmc = new FormHttpMessageConverter();
fmc.addPartConverter(new Jaxb2RootElementHttpMessageConverter());
fmc.addPartConverter(new ResourceHttpMessageConverter());
messageConverters.add(fmc);
return messageConverters;
}
Request headers :
private org.springframework.http.HttpHeaders getRequestHeaders(String contentType) throws Exception {
....
.....
org.springframework.http.HttpHeaders httpHeaders = new org.springframework.http.HttpHeaders();
httpHeaders.set("Accept", "applicaiton/company+xml");
httpHeaders.set("Content-Type", "multipart/form-data");
String consumer = "<AppUserId>";
httpHeaders.set("consumer", consumer);
String tmStamp= getCurrentTimeStamp();
httpHeaders.set("timestamp", tmStamp);
...
...
return httpHeaders;
}

Crypto Bad Padding Exception

I really need some help. I am working on this assignment in school. I'm supposed to read a txt file into a list or string, and Encrypt that list of string, save it and Decrypt it back into a list of string. I was able to Encrypt it and save it, but when I try to Decrypt it back, it give me an error message about Bad Padding. I really don't how to fix this problem. Any help will be really good.
This is my code for Encrypting it
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.*;
import java.nio.file.*;
import java.security.*;
import java.util.*;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class WordAnalysisMenu {
private static KeyGenerator kgen;
private static SecretKey key;
private static byte[] iv = null;
static Scanner sc = new Scanner(System.in);
private static void init(){
try {
kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
key = kgen.generateKey();
} catch (NoSuchAlgorithmException e) {
}
}
public static void main (String [] arge) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IOException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
List<String> warPeace = new ArrayList<>();
while(true) {
int choice = menu();
switch(choice) {
case 0:
break;
case 1:
//select file for reading
warPeace = readFile();
break;
case 7:
//apply the cipher and save it to a file
init();
Frame frame = new Frame();
FileDialog fileDialog = new FileDialog(frame, "", FileDialog.SAVE);
fileDialog.setVisible(true);
Path path = Paths.get(fileDialog.getDirectory() + fileDialog.getFile());
iv = ListEncrypter(warPeace, path, key);
break;
case 8:
// read the ciper file, decode, and print
init();
frame = new Frame();
fileDialog = new FileDialog(frame, "", FileDialog.LOAD);
fileDialog.setVisible(true);
Path inputFile = Paths.get(fileDialog.getDirectory() + fileDialog.getFile());
warPeace = ListDecrypter(inputFile, key, iv);
break;
case 9:
System.out.println("Good bye!");
System.exit(0);
break;
default:
break;
}
}
}
public static int menu() {
int choice = 0;
System.out.println("\nPlease make a selection: ");
System.out.println("1.\t Select a file for reading.");
System.out.println("7.\t Apply cipher & save");
System.out.println("8.\t Read encoded file");
System.out.println("9.\t Exit");
Scanner scan = new Scanner(System.in);
try {
choice = scan.nextInt();
scan.nextLine();
}
catch(InputMismatchException ime) {
System.out.println("Invalid input!");
}
return choice;
}
public static List<String> readFile() {
List<String> word = new ArrayList<String>();
Frame f = new Frame();
FileDialog saveBox = new FileDialog(f, "Reading text file", FileDialog.LOAD);
saveBox.setVisible(true);
String insName = saveBox.getFile();
String fileSavePlace = saveBox.getDirectory();
File inFile = new File(fileSavePlace + insName);
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(inFile));
String line;
while (((line = in.readLine()) != null)) {
System.out.println(line);
String s = new String();
word.add(line);
}
} catch (IOException io) {
System.out.println("There Was An Error Reading The File");
} finally {
try {
in.close();
} catch (Exception e) {
e.getMessage();
}
}
return word;
}
private static byte[] ListEncrypter(List<String> content, Path outputFile, SecretKey key)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//Cipher encryptCipher = Cipher.getInstance("AES/CFB8/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
StringBuilder sb = new StringBuilder();
content.stream().forEach(e -> sb.append(e).append(System.lineSeparator()));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(encryptCipher.doFinal(sb.toString().getBytes()));
//cipherOutputStream.write(sb.toString().getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
Files.copy(inputStream, outputFile, StandardCopyOption.REPLACE_EXISTING);
return encryptCipher.getIV();
}
private static List<String> ListDecrypter(Path inputFile, SecretKey key, byte[] iv) throws
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, BadPaddingException {
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//Cipher decryptCipher = Cipher.getInstance("AES/CBC/CFB8NoPadding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
decryptCipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
List<String> fileContent = new ArrayList<>();
String line = null;
ByteArrayInputStream inputStream = new ByteArrayInputStream(Files.readAllBytes(inputFile));
try(CipherInputStream chipherInputStream = new CipherInputStream(new FileInputStream(inputFile.toFile()), decryptCipher);
BufferedReader br = new BufferedReader(new InputStreamReader(chipherInputStream))) {
while ((line = br.readLine()) != null) {
System.out.println(line);
//fileContent.add(line);
}
}
return null;
}
}
This is the error message.
Exception in thread "main" java.io.IOException:
javax.crypto.BadPaddingException: Given final block not properly
padded

HttpsURLConnection for rest service call

i am using HttpsURLConnection for calling POST method and i am unable to add request payload to the call. same request works when i execute manually from soapui tool. does any one know how to do this?
Here is the java code is am using:
// Keystore
String jksFile = "/Users/......jks";
String password = "password";
System.setProperty("javax.net.ssl.keyStore", jksFile);
System.setProperty("javax.net.ssl.keyStorePassword", password);
String u = "https://example.com:443/private/loan-application";
URL url = new URL(u);
String version = "3";
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Accept", "application/json;v=" + version);
conn.setRequestProperty("Api-Key", "XYZ");
String jsonParamString = "{\"didNumber\":\"DI457\", \" .... ";
//Create JSONObject here
JSONObject jsonParam = new JSONObject();
byte[] postData = jsonParamString.toString().getBytes();
Map<String, List<String>> requestProperties = conn.getRequestProperties();
displayHeaders(requestProperties);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
int respCode = conn.getResponseCode();
System.out.println("Response headers:");
displayHeaders(
conn.getHeaderFields());
InputStream is = null;
if (respCode == 200 || respCode == 203) {
is = conn.getInputStream();
}
if (is == null) {
System.out.println("Using error stream");
is = conn.getErrorStream();
}
is.close();
One possible explanation for why your HttpsURLConnection call is failing is that you have not configured your SSL settings properly. Specifically, the domain example.com is presenting a certificate which is not in your trust store, and therefore your program is failing during the SSL handshake. Try adding the following code, which will configure your program to trust all certificates:
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { }
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { }
public X509Certificate[] getAcceptedIssuers() { return null; }
};
sslContext.init(null, new TrustManager[]{tm}, null);
conn.setSSLSocketFactory(sslContext.getSocketFactory());
Note that you should probably not use this code in production, because it accepts any site as secure. In production, you should configure your program to only accept trusted certificates.

jaxrs.ResteasyClient download file

Request a webAPI that gives me a ZIP file. Now my question:
How to download that file with jaxrs.ResteasyClient. Here is what I have but it does not work for me.
// In
Reader reader = client.target(url).request().get().readEntity(Reader.class);
BufferedReader bufferedReader = new BufferedReader(reader);
// Out
File out = new File("C:\\tmp\\test.zip");
FileWriter fileWriter = new FileWriter(out);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
String s = null;
while (true) {
s = bufferedReader.readLine();
if (s == null) {
break;
}
bufferedWriter.write(s);
}
bufferedWriter.flush();
bufferedWriter.close();
bufferedReader.close();
I have no idea if this makes sense, but I do not find any good documentation about reading a file instead of a bean object.
Resolved this issue by not using jaxrs.ResteasyClient. Apache HTTPClient was my friend!
private void getFileByURL(String url, String target) throws URISyntaxException, IOException {
HttpClientBuilder builder = HttpClients.custom().build();
CloseableHttpClient client = builder.build();
HttpResponse response = client.execute(new HttpGet(new URI(url)));
BufferedInputStream bufferedInputStream = new BufferedInputStream(response.getEntity().getContent());
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File(target)));
int inByte;
while ((inByte = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(inByte);
}
bufferedInputStream.close();
bufferedOutputStream.close();
EntityUtils.consume(response.getEntity());
}

Resources