}
// See if this key has already been processed. If so then just return the result
String id = elem.getAttributeNS(null, "Id");
if (!"".equals(id)) {
WSSecurityEngineResult result = wsDocInfo.getResult(id);
if (result != null &&
WSConstants.ENCR == (Integer)result.get(WSSecurityEngineResult.TAG_ACTION)
) {
return java.util.Collections.singletonList(result);
}
}
if (data.getDecCrypto() == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noDecCryptoFile");
}
if (data.getCallbackHandler() == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCallback");
}
//
// lookup xenc:EncryptionMethod, get the Algorithm attribute to determine
// how the key was encrypted. Then check if we support the algorithm
//
String encryptedKeyTransportMethod = X509Util.getEncAlgo(elem);
if (encryptedKeyTransportMethod == null) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "noEncAlgo"
);
}
if (WSConstants.KEYTRANSPORT_RSA15.equals(encryptedKeyTransportMethod)
&& !data.isAllowRSA15KeyTransportAlgorithm()
&& algorithmSuite != null
&& !algorithmSuite.getKeyWrapAlgorithms().contains(WSConstants.KEYTRANSPORT_RSA15)) {
LOG.debug(
"The Key transport method does not match the requirement"
);
throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
}
// Check BSP Compliance
checkBSPCompliance(elem, encryptedKeyTransportMethod, data.getBSPEnforcer());
Cipher cipher = WSSecurityUtil.getCipherInstance(encryptedKeyTransportMethod);
//
// Now lookup CipherValue.
//
Element tmpE =
WSSecurityUtil.getDirectChildElement(
elem, "CipherData", WSConstants.ENC_NS
);
Element xencCipherValue = null;
if (tmpE != null) {
xencCipherValue =
WSSecurityUtil.getDirectChildElement(tmpE, "CipherValue", WSConstants.ENC_NS);
}
if (xencCipherValue == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noCipher");
}
STRParser strParser = new EncryptedKeySTRParser();
X509Certificate[] certs =
getCertificatesFromEncryptedKey(elem, data, wsDocInfo, strParser);
// Check for compliance against the defined AlgorithmSuite
if (algorithmSuite != null) {
AlgorithmSuiteValidator algorithmSuiteValidator = new
AlgorithmSuiteValidator(algorithmSuite);
algorithmSuiteValidator.checkAsymmetricKeyLength(certs[0]);
algorithmSuiteValidator.checkEncryptionKeyWrapAlgorithm(
encryptedKeyTransportMethod
);
}
try {
PrivateKey privateKey = data.getDecCrypto().getPrivateKey(certs[0], data.getCallbackHandler());
OAEPParameterSpec oaepParameterSpec = null;
if (WSConstants.KEYTRANSPORT_RSAOEP.equals(encryptedKeyTransportMethod)
|| WSConstants.KEYTRANSPORT_RSAOEP_XENC11.equals(encryptedKeyTransportMethod)) {
// Get the DigestMethod if it exists
String digestAlgorithm = getDigestAlgorithm(elem);
String jceDigestAlgorithm = "SHA-1";
if (digestAlgorithm != null && !"".equals(digestAlgorithm)) {
jceDigestAlgorithm = JCEMapper.translateURItoJCEID(digestAlgorithm);
}
String mgfAlgorithm = getMGFAlgorithm(elem);
MGF1ParameterSpec mgfParameterSpec = new MGF1ParameterSpec("SHA-1");
if (mgfAlgorithm != null) {
if (WSConstants.MGF_SHA224.equals(mgfAlgorithm)) {
mgfParameterSpec = new MGF1ParameterSpec("SHA-224");
} else if (WSConstants.MGF_SHA256.equals(mgfAlgorithm)) {
mgfParameterSpec = new MGF1ParameterSpec("SHA-256");
} else if (WSConstants.MGF_SHA384.equals(mgfAlgorithm)) {
mgfParameterSpec = new MGF1ParameterSpec("SHA-384");
} else if (WSConstants.MGF_SHA512.equals(mgfAlgorithm)) {
mgfParameterSpec = new MGF1ParameterSpec("SHA-512");
}
}
PSource.PSpecified pSource = PSource.PSpecified.DEFAULT;
byte[] pSourceBytes = getPSource(elem);
if (pSourceBytes != null) {
pSource = new PSource.PSpecified(pSourceBytes);
}
oaepParameterSpec =
new OAEPParameterSpec(
jceDigestAlgorithm, "MGF1", mgfParameterSpec, pSource
);
}
if (oaepParameterSpec == null) {
cipher.init(Cipher.UNWRAP_MODE, privateKey);
} else {
cipher.init(Cipher.UNWRAP_MODE, privateKey, oaepParameterSpec);
}
} catch (Exception ex) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
}
List<String> dataRefURIs = getDataRefURIs(elem);
byte[] encryptedEphemeralKey = null;
byte[] decryptedBytes = null;
try {
encryptedEphemeralKey = getDecodedBase64EncodedData(xencCipherValue);
String keyAlgorithm = JCEMapper.translateURItoJCEID(encryptedKeyTransportMethod);
decryptedBytes = cipher.unwrap(encryptedEphemeralKey, keyAlgorithm, Cipher.SECRET_KEY).getEncoded();
} catch (IllegalStateException ex) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
} catch (Exception ex) {
decryptedBytes = getRandomKey(dataRefURIs, elem.getOwnerDocument(), wsDocInfo);
}
List<WSDataRef> dataRefs = decryptDataRefs(dataRefURIs, elem.getOwnerDocument(), wsDocInfo,
decryptedBytes, data);
WSSecurityEngineResult result = new WSSecurityEngineResult(
WSConstants.ENCR,
decryptedBytes,
encryptedEphemeralKey,
dataRefs,
certs
);
result.put(
WSSecurityEngineResult.TAG_ENCRYPTED_KEY_TRANSPORT_METHOD,
encryptedKeyTransportMethod
);
result.put(WSSecurityEngineResult.TAG_ID, elem.getAttributeNS(null, "Id"));
result.put(WSSecurityEngineResult.TAG_X509_REFERENCE_TYPE, strParser.getCertificatesReferenceType());
wsDocInfo.addResult(result);
wsDocInfo.addTokenElement(elem);
return java.util.Collections.singletonList(result);
}