JSF1094 error happened when use Flash in cluster env - jsf

I am using primefaces 11 in a cluster env(alb + two wildfly 17 + distributable setting).
when I use Flash to pass parameter from page1 to page2, I got the following error, and the parameters can no be passed.
[javax.enterprise.resource.webcontainer.jsf.flash] (default task-29) JSF1094: Could not decode flash data from incoming cookie value Invalid characters in decrypted value. Processing will continue, but the flash is unavailable for this request.
If I run it in only one server, the parameters can be passed normally.
set data
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put(REDIRECT_DATA_KEY, rData);
get data
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
return (RedirectData) flash.get(REDIRECT_DATA_KEY);
How I can solve it?

From Red Hat offical support:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
...
<env-entry>
<env-entry-name>jsf/FlashSecretKey</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<!-- http://www.digitalsanctuary.com/aes-key-generator.php -->
<env-entry-value>Ya+MAlSDzgC3LAXgfEoPA/J6saEp7MtjjF0P6LP69nGk=</env-entry-value>
</env-entry>
<distributable/>
</web-app>
jsf/FlashSecretKey is base64 encoded AES 256bit key which used for encrypting flash scope cookie like csfcfc=K8auYBA%3D;.
The key can generate by the following code:
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Main {
public static void main(String ... args) throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // key length is 256 byte
SecretKey secretKey = keyGen.generateKey();
System.out.println("key: " + Base64.getEncoder().encodeToString(secretKey.getEncoded()));
}
}
The flash cookie value Set-Cookie: csfcfc=K8auYBA%3D; is AES encrypted by default. If JNDI key java:comp/env/jsf/FlashSecretKey is not set, Mojarra will try to create a random secret key that is used in AES encryption for the flash cookie value.
In case of cluster environment, that behavior will cause each clustered EAP instance has a different secret key. As a result, Mojarra is unable to restore clustered flash cookie value with the following error message:
20:09:40,317 SEVERE [javax.enterprise.resource.webcontainer.jsf.flash] (default task-1)
JSF1094: Could not decode flash data from incoming cookie value Invalid characters in decrypted value. Processing will continue, but the flash is unavailable for this request.

Related

Trying to symmetrically encrypt a value for storage in the client (httpOnly cookie) and having an issue decrypting

I am trying to encrypt a value on my server with a private key to store it on the client within an httpOnly cookie.
I am having trouble with the encryption/decryption lifecycle
function encrypt(input) {
const encryptedData = crypto.privateEncrypt(
privateKey,
Buffer.from(input)
)
return encryptedData.toString('base64')
}
function decrypt(input) {
const decryptedData = crypto.privateDecrypt(
{ key: privateKey },
Buffer.from(input, 'base64'),
)
return decryptedData.toString()
}
const enc = encrypt('something moderately secret')
const dec = decrypt(enc)
console.log(dec) // 'something moderately secret'
However the crypto.privateDecrypt function is throwing with
Error: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
Side question, is it safe to reuse the same private key the server uses to sign JWTs. It's an rsa key generated using ssh-keygen -t rsa -b 4096 -m PEM -f RS256.key
So, you don't use crypto.privateEncrypt() with crypto.privateDecrypt(). That's not how they work. Those functions are for asymmetric encryption, not for symmetric encryption. You use either of these two pairs:
crypto.publicEncrypt() ==> crypto.privateDescrypt()
crypto.privateEncrypt() ==> crypto.publicDecrypt()
So, that's why you're getting the error you're getting. The nodejs doc for crypto.privateDecript() says this:
Decrypts buffer with privateKey. buffer was previously encrypted using the corresponding public key, for example using crypto.publicEncrypt().
If what you really want is symmetric encryption, there are a bunch of options in the crypto module for that. There are some examples shown here: https://www.section.io/engineering-education/data-encryption-and-decryption-in-node-js-using-crypto/ and https://fireship.io/lessons/node-crypto-examples/#symmetric-encryption-in-nodejs.

Create RSA-SHA256 sign with PEM key

I've been creating a gateway for a legacy service, this legacy service needs a signature as a body parameter of a PUT request, in order to create this sign I need to follow the following steps:
Create a hash with certain text as data, this hash needs to be SHA256.
Encrypt the result of the hash using RSA with a PEM key
Encode the result of the RSA to Base64
Following the previous steps I create the following code
export class Signature {
// class body
public static sign(text: string){
const key = readFileSync('key.pem')
const passphrase = '12345678'
const createdSign = createSign('RSA-SHA256')
createdSign.write(text)
createdSign.end()
return createdSign.sign({ key, passphrase }).toString('base64')
}
}
But I'm not sure if this the correct implementation, taking into consideration the previous steps, and the existence of the hash API in NodeJS.
If someone could tell me if I'm correctly implementing this algorithm.

Error while trying to encrypt using AES-128-ECB algorithm

I've been trying to encrypt some messages using "crypto" library in NodeJS, and I'm getting the following error:
(node:31732) UnhandledPromiseRejectionWarning: Error: error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
at Cipheriv.final (internal/crypto/cipher.js:164:28)
at self.test (...)
self.test = async function(info, object) {
let message = {
info: info,
object: object
};
let iv = crypto.randomBytes(16)
let key = Buffer.from(config.key, 'utf8');
let cipher = crypto.createCipheriv("aes-128-ecb", key, '');
cipher.setAutoPadding(false)
let encrypted = cipher.update(JSON.stringify(message));
encrypted = Buffer.concat([iv, encrypted, cipher.final()]);
encrypted = encrypted.toString('base64');
console.log(encrypted);
}
The error is originating from the cipher.final() call as seen in the stack above.
I can't figure out what this error says and how to resolve it. Unfortunately due to constraints (I'm trying to send encrypted data over UDP) I'm not able to use algorithms like CBC (messages are not received in the same order they are encrypted).
Any help is greatly appreciated!
cipher.setAutoPadding(false) sets padding to false, and ECB and CBC only operate on full blocks - which is the reason why padding is required for anything that is not a multiple of the block size. You should remove the line (preferred) or create your own padding (and fall in a trap of inventing your own crypto).
Note that both ECB and CBC are inherently vulnerable to plaintext / padding oracle attacks. ECB is insecure anyway and it doesn't use an IV. For transport mode security you need a MAC or you should use an authenticated cipher. Transport security is hard to accomplish, try DTLS.

Issue with base64 encoding of data using HMAC

Using Nodejs, I'm attempting to generate a HMAC SHA256, base64-encoded signature of an XML message. I currently have the signature generation working using PHP.
The process seems fairly straightforward, and I'm able to generate base64-encoded value with Nodejs but, for some reason, the value does not match and is much shorter than what I get using PHP.
Below, I've included an example PHP script and result as well as the Nodejs implementation and result. With Nodejs, I'm using the native crypto module.
// PHP implementation
$xml = <<<EOD
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<record>
<id>1</id>
<first_name>Carlos</first_name>
<last_name>Ruiz</last_name>
<email>cruiz0#engadget.com</email>
<gender>Male</gender>
<ip_address>156.225.191.154</ip_address>
</record>
</dataset>
EOD;
$secret = 'secret';
$sig = base64_encode(hash_hmac('sha256', $xml, $secret));
echo $sig;
Result:
ODhkYTc1YmQzNzc0NWUyNDJlNjY3YTY1NzZhYzFhZGYwOTJlMTIxODdjNzYxOWYyNGQxNGExOGVkYTIyZDQ0ZQ==
// Nodejs implementation
var crypto = require('crypto');
fs.readFile('example.xml', 'utf-8', function(err, data) {
function sig(str, key) {
return crypto.createHmac('sha256', key)
.update(str)
.digest('base64');
}
console.log(sig(data, 'secret'));
});
Result:
iNp1vTd0XiQuZnpldqwa3wkuEhh8dhnyTRShjtoi1E4=
I've spent the day trying to figure this out and after a year+ of using Stack Overflow, this is my first question.
Any assistance would be greatly appreciated!
The problem here is that PHP's hash_hmac() returns a hex-encoded string by default (see the $raw_output parameter here), so you are base64-encoding a hex string instead of the actual of the raw, binary result.
So change this:
$sig = base64_encode(hash_hmac('sha256', $xml, $secret));
to:
$sig = base64_encode(hash_hmac('sha256', $xml, $secret, true));

Docusign : One or both of Username and Password are invalid

I was testing Docusign PHP API and trying the following code:
$envelopeId = '3e979aac-1d8d-4ab9-rand-envelopid';
$api = new APIService();
$api->setCredentials('devaccountemail', 'devaccountpassword');
$userName = 'Test Signer';
$userEmail = 'random#randor.com';
$userId = '457';
$RequestRecipientTokenParams = new RequestRecipientToken();
$RequestRecipientTokenParams->EnvelopeID = $envelopeId;
$RequestRecipientTokenParams->Username = $userName;
$RequestRecipientTokenParams->Email = $userEmail;
$RequestRecipientTokenParams->ClientUserID = $userId;
$RequestRecipientTokenParams->AuthenticationAssertion->AssertionID = rand(0, 999);
$RequestRecipientTokenParams->AuthenticationAssertion->AuthenticationInstant = date("Y")."-".date("m")."-".date("d")."T00:00:00.00";
$RequestRecipientTokenParams->AuthenticationAssertion->AuthenticationMethod = RequestRecipientTokenAuthenticationAssertionAuthenticationMethod::Email;
$RequestRecipientTokenParams->AuthenticationAssertion->SecurityDomain = "local IP Address";
$RequestRecipientTokenParams->ClientURLs->OnAccessCodeFailed = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnAccessCodeFailed";
$RequestRecipientTokenParams->ClientURLs->OnCancel = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnCancel";
$RequestRecipientTokenParams->ClientURLs->OnDecline = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnDecline";
$RequestRecipientTokenParams->ClientURLs->OnException = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnException";
$RequestRecipientTokenParams->ClientURLs->OnFaxPending = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnFaxPending";
$RequestRecipientTokenParams->ClientURLs->OnIdCheckFailed = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnIdCheckFailed";
$RequestRecipientTokenParams->ClientURLs->OnSessionTimeout ="https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSessionTimeout";
$RequestRecipientTokenParams->ClientURLs->OnSigningComplete = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSigningComplete";
$RequestRecipientTokenParams->ClientURLs->OnTTLExpired = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnTTLExpired";
$RequestRecipientTokenParams->ClientURLs->OnViewingComplete = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnViewingComplete";
$RequestRecipientTokenResponse = $api->RequestRecipientToken($RequestRecipientTokenParams);
I got the following Error:
SoapFault : One or both of Username and Password are invalid.
The credentials provided by me are valid and I can login to demo.docusign.net account with these credentials. I'm not sure where I'm doing it wrong.
Here is the SOAP request that is being generated:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.docusign.net/API/3.0"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<SOAP-ENV:Header>
<wsa:Action>http://www.docusign.net/API/3.0/RequestRecipientToken</wsa:Action>
<wsa:To>https://www.docusign.net/API/3.0/api.asmx</wsa:To>
<wsa:MessageID>uudi:638fd49c-2516-12a9-8159-17a9c602975e</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2013-09-18T12:30:20Z</wsu:Created>
<wsu:Expires>2013-09-18T12:35:20Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken>
<wsse:Username>bhargav.bonu#somedomain.com</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-
token-profile-1.0#PasswordText">mypassword</wsse:Password>
<wsse:Nonce>0PZkAUVbHHiyjV8KZrN6x2x0S6cQ5WbAjTH4yn8dnc4=</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd">2013-09-18T12:29:18Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:RequestRecipientToken>
<ns1:EnvelopeID>3e979aac-1d8d-4ab9-a45c-randElem</ns1:EnvelopeID>
<ns1:Username>Test Signer</ns1:Username>
<ns1:Email>Guest</ns1:Email>
<ns1:AuthenticationAssertion>
<ns1:AssertionID>175</ns1:AssertionID>
<ns1:AuthenticationInstant>2013-09-18T00:00:00.00</ns1:AuthenticationInstant>
<ns1:AuthenticationMethod>Email</ns1:AuthenticationMethod>
<ns1:SecurityDomain>192.168.0.43</ns1:SecurityDomain></ns1:AuthenticationAssertion>
<ns1:ClientURLs>
<ns1:OnSigningComplete>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSigningComplete</ns1:OnSigningComplete>
<ns1:OnViewingComplete>https://YourApp.com/DocuSignCallback.html?
envelopeId=YourEnvelopeId&event=OnViewingComplete</ns1:OnViewingComplete>
<ns1:OnCancel>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnCancel</ns1:OnCancel>
<ns1:OnDecline>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnDecline</ns1:OnDecline>
<ns1:OnSessionTimeout>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSessionTimeout</ns1:OnSessionTimeout>
<ns1:OnTTLExpired>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnTTLExpired</ns1:OnTTLExpired>
<ns1:OnException>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnException</ns1:OnException>
<ns1:OnAccessCodeFailed>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnAccessCodeFailed</ns1:OnAccessCodeFailed>
<ns1:OnIdCheckFailed>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnIdCheckFailed</ns1:OnIdCheckFailed>
<ns1:OnFaxPending>https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnFaxPending</ns1:OnFaxPending>
</ns1:ClientURLs>
</ns1:RequestRecipientToken>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
That error indicates that the DocuSign user credentials you're providing in the request to authenticate the API call are not valid. The code you included in this post is irrelevant, really, as any API call would result in this error if either the username or password you're providing to authenticate the request is invalid.
If you haven't already done so, I'd suggest that you produce a trace of the full XML Request (i.e., including headers) to closely examine the authentication credentials that you're providing in the request. The best way to troubleshoot issues like this is to examine what's going over the wire (rather than trying to troubleshoot code that's producing what's going over the wire) -- once the issue in the XML is identified, it should be easy to fix in the code.
Regarding the "username or password invalid" error -- it might be caused by the fact that your not including your Integrator Key within Username. From page 18 of the DocuSign SOAP API Guide (http://www.docusign.com/sites/default/files/DocuSignAPI_Guide.pdf):
The integrator key must be placed in front of the user ID that is in the Username node of the UsernameToken. The integrator key must be wrapped with brackets, “[ and ]”. Example format:
<wsse:Username>[Integrator Key]2988541c-4ec7-4245-b520-f2d324062ca3</wsse:Username>
The Integrator Key must be included in all API requests, as DocuSign requires it in order to identify the integrating application.

Resources