Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.utils.EncryptionConstants;
import org.apache.xml.security.utils.JavaUtils;
import org.w3c.dom.Element;

Expand Down Expand Up @@ -318,6 +319,22 @@ public static void registerDefaultAlgorithms() {
XMLCipher.RSA_OAEP_11,
new Algorithm("RSA", "RSA/ECB/OAEPPadding", "KeyTransport")
);
algorithmsMap.put(
EncryptionConstants.ALGO_ID_KEYTRANSPORT_MLKEM_512,
new Algorithm("ML-KEM-512", "ML-KEM-512", "KeyTransport")
);
algorithmsMap.put(
EncryptionConstants.ALGO_ID_KEYTRANSPORT_MLKEM_768,
new Algorithm("ML-KEM-768", "ML-KEM-768", "KeyTransport")
);
algorithmsMap.put(
EncryptionConstants.ALGO_ID_KEYTRANSPORT_MLKEM_1024,
new Algorithm("ML-KEM-1024", "ML-KEM-1024", "KeyTransport")
);
algorithmsMap.put(
EncryptionConstants.ALGO_ID_KEYTRANSPORT_GENERIC_HYBRID,
new Algorithm("", "", "KeyTransport")
);
algorithmsMap.put(
XMLCipher.DIFFIE_HELLMAN,
new Algorithm("", "", "KeyAgreement")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,71 @@ public interface EncryptionMethod {
*/
String getMGFAlgorithm();

/**
* Returns the Key Encapsulation Method algorithm URI used for KEM-based key transport
* (W3C "XML Security: Generic Hybrid Cipher", https://www.w3.org/TR/xmlsec-generic-hybrid/),
* i.e. the {@code Algorithm} attribute of the {@code ghc:KeyEncapsulationMethod} element nested
* inside {@code ghc:GenericHybridCipherMethod}.
*
* @return the key encapsulation algorithm, or {@code null} if this is not a Generic Hybrid
* Cipher {@code EncryptionMethod}.
*/
String getKeyEncapsulationAlgorithm();

/**
* Sets the Key Encapsulation Method algorithm URI. See {@link #getKeyEncapsulationAlgorithm()}.
*
* @param algorithm the key encapsulation algorithm.
*/
void setKeyEncapsulationAlgorithm(String algorithm);

/**
* Returns the {@code xenc11:KeyDerivationMethod} nested inside {@code ghc:KeyEncapsulationMethod},
* used to derive the data-encapsulation (AES key-wrap) key from the KEM shared secret.
*
* @return the key derivation method, or {@code null} if not set.
*/
KeyDerivationMethod getKeyEncapsulationKeyDerivationMethod();

/**
* Sets the key derivation method. See {@link #getKeyEncapsulationKeyDerivationMethod()}.
*
* @param keyDerivationMethod the key derivation method.
*/
void setKeyEncapsulationKeyDerivationMethod(KeyDerivationMethod keyDerivationMethod);

/**
* Returns the {@code ghc:KeyLen} value nested inside {@code ghc:KeyEncapsulationMethod}: the
* length, in bytes, of the derived data-encapsulation key.
*
* @return the key length in bytes, or a non-positive value if not set.
*/
int getKeyEncapsulationKeyLength();

/**
* Sets the derived key length in bytes. See {@link #getKeyEncapsulationKeyLength()}.
*
* @param keyLength the key length in bytes.
*/
void setKeyEncapsulationKeyLength(int keyLength);

/**
* Returns the Data Encapsulation Method algorithm URI, i.e. the {@code Algorithm} attribute of
* the {@code ghc:DataEncapsulationMethod} element nested inside {@code ghc:GenericHybridCipherMethod}
* (typically an AES-KeyWrap algorithm URI).
*
* @return the data encapsulation algorithm, or {@code null} if this is not a Generic Hybrid
* Cipher {@code EncryptionMethod}.
*/
String getDataEncapsulationAlgorithm();

/**
* Sets the Data Encapsulation Method algorithm URI. See {@link #getDataEncapsulationAlgorithm()}.
*
* @param algorithm the data encapsulation algorithm.
*/
void setDataEncapsulationAlgorithm(String algorithm);

/**
* Returns an iterator over all the additional elements contained in the
* <code>EncryptionMethod</code>.
Expand Down
292 changes: 283 additions & 9 deletions src/main/java/org/apache/xml/security/encryption/XMLCipher.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
import org.apache.xml.security.encryption.keys.content.derivedKey.ConcatKDFParamsImpl;
import org.apache.xml.security.encryption.keys.content.derivedKey.HKDFParamsImpl;
import org.apache.xml.security.encryption.keys.content.derivedKey.KDFParams;
import org.apache.xml.security.encryption.keys.content.derivedKey.KeyDerivationMethodImpl;
import org.apache.xml.security.encryption.params.ConcatKDFParams;
import org.apache.xml.security.encryption.params.HKDFParams;
import org.apache.xml.security.encryption.params.KeyAgreementParameters;
import org.apache.xml.security.encryption.params.KeyDerivationParameters;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.utils.EncryptionConstants;
import org.apache.xml.security.utils.KeyUtils;
import org.w3c.dom.Document;

import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
Expand Down Expand Up @@ -284,6 +286,54 @@ public static KeyDerivationParameters constructKeyDerivationParameter(KeyDerivat
throw new XMLEncryptionException("unknownAlgorithm", keyDerivationAlgorithm);
}

/**
* Construct a {@code KeyDerivationMethod} DOM element from the given {@link KeyDerivationParameters}.
* The inverse of {@link #constructKeyDerivationParameter(KeyDerivationMethod, int)}. Supports the same
* two key derivation functions as the ECDH-ES/X25519/X448 key-agreement path: ConcatKDF and HKDF.
*
* @param doc the {@link Document} in which the {@code KeyDerivationMethod} element will be created
* @param keyDerivationParameter the key derivation parameters (e.g. {@link HKDFParams} or {@link ConcatKDFParams})
* @return the constructed {@code KeyDerivationMethod}
* @throws XMLEncryptionException if the key derivation algorithm is not supported
*/
public static KeyDerivationMethod constructKeyDerivationMethod(Document doc, KeyDerivationParameters keyDerivationParameter)
throws XMLEncryptionException {
KeyDerivationMethodImpl keyDerivationMethod = new KeyDerivationMethodImpl(doc);
keyDerivationMethod.setAlgorithm(keyDerivationParameter.getAlgorithm());

KDFParams kdfParams;
if (keyDerivationParameter instanceof ConcatKDFParams) {
ConcatKDFParams kdfParameters = (ConcatKDFParams) keyDerivationParameter;
ConcatKDFParamsImpl concatKDFParams = new ConcatKDFParamsImpl(doc);
concatKDFParams.setDigestMethod(kdfParameters.getDigestAlgorithm());
concatKDFParams.setAlgorithmId(kdfParameters.getAlgorithmID());
concatKDFParams.setPartyUInfo(kdfParameters.getPartyUInfo());
concatKDFParams.setPartyVInfo(kdfParameters.getPartyVInfo());
concatKDFParams.setSuppPubInfo(kdfParameters.getSuppPubInfo());
concatKDFParams.setSuppPrivInfo(kdfParameters.getSuppPrivInfo());
kdfParams = concatKDFParams;
} else if (keyDerivationParameter instanceof HKDFParams) {
HKDFParams kdfParameters = (HKDFParams) keyDerivationParameter;
HKDFParamsImpl hkdfParams = new HKDFParamsImpl(doc);
hkdfParams.setPRFAlgorithm(kdfParameters.getHmacHashAlgorithm());
Base64.Encoder base64Encoder = Base64.getEncoder();
if (kdfParameters.getSalt() != null) {
hkdfParams.setSalt(base64Encoder.encodeToString(kdfParameters.getSalt()));
}
if (kdfParameters.getInfo() != null) {
hkdfParams.setInfo(base64Encoder.encodeToString(kdfParameters.getInfo()));
}
hkdfParams.setKeyLength(kdfParameters.getKeyBitLength() / 8);
kdfParams = hkdfParams;
} else {
throw new XMLEncryptionException("KeyDerivation.UnsupportedAlgorithm",
keyDerivationParameter.getAlgorithm(), keyDerivationParameter.getClass().getName());
}

keyDerivationMethod.setKDFParams(kdfParams);
return keyDerivationMethod;
}

/**
* Method hexStringToByteArray converts hex string to byte array.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.xml.security.encryption.params;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.AlgorithmParameterSpec;

/**
* This class is used to pass parameters to the Key Encapsulation Mechanism (KEM) based key
* transport, as specified in the W3C "XML Security: Generic Hybrid Cipher" note
* (https://www.w3.org/TR/xmlsec-generic-hybrid/). Unlike Diffie-Hellman key agreement
* ({@link KeyAgreementParameters}), a KEM has no ephemeral originator key pair: the
* encapsulating party only needs the recipient's public key, and the decapsulating party
* only needs the recipient's private key.
*/
public class KeyEncapsulationParameters implements AlgorithmParameterSpec {

private final String keyEncapsulationAlgorithm;
private final KeyDerivationParameters keyDerivationParameter;

private PublicKey recipientPublicKey;
private PrivateKey recipientPrivateKey;

public KeyEncapsulationParameters(String keyEncapsulationAlgorithm, KeyDerivationParameters keyDerivationParameter) {
this.keyEncapsulationAlgorithm = keyEncapsulationAlgorithm;
this.keyDerivationParameter = keyDerivationParameter;
}

public String getKeyEncapsulationAlgorithm() {
return keyEncapsulationAlgorithm;
}

public KeyDerivationParameters getKeyDerivationParameter() {
return keyDerivationParameter;
}

public PublicKey getRecipientPublicKey() {
return recipientPublicKey;
}

public void setRecipientPublicKey(PublicKey recipientPublicKey) {
this.recipientPublicKey = recipientPublicKey;
}

public PrivateKey getRecipientPrivateKey() {
return recipientPrivateKey;
}

public void setRecipientPrivateKey(PrivateKey recipientPrivateKey) {
this.recipientPrivateKey = recipientPrivateKey;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class DEREncodedKeyValue extends Signature11ElementProxy implements KeyIn
private static final String[] supportedKeyTypes = { "RSA", "DSA", "EC",
"DiffieHellman", "DH", "XDH", "X25519", "X448",
"EdDSA", "Ed25519", "Ed448",
"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024",
"RSASSA-PSS"};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,12 @@ public enum DIRECTION {
public static final String NS_DSIG = "http://www.w3.org/2000/09/xmldsig#";
public static final String NS_DSIG_MORE ="http://www.w3.org/2001/04/xmldsig-more#";
public static final String NS_DSIG_MORE_2007_05 = "http://www.w3.org/2007/05/xmldsig-more#";
public static final String NS_DSIG_MORE_2021_04 = "http://www.w3.org/2021/04/xmldsig-more#";
public static final String NS_DSIG11 = "http://www.w3.org/2009/xmldsig11#";
public static final String NS_WSSE11 = "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd";
public static final String NS_XOP = "http://www.w3.org/2004/08/xop/include";
/** W3C "XML Security: Generic Hybrid Cipher" namespace (https://www.w3.org/TR/xmlsec-generic-hybrid/) */
public static final String NS_GHC = "http://www.w3.org/2010/xmlsec-ghc#";

public static final String PREFIX_XENC = "xenc";
public static final String PREFIX_XENC11 = "xenc11";
Expand All @@ -162,6 +165,22 @@ public enum DIRECTION {
public static final QName TAG_xenc_OAEPparams = new QName(NS_XMLENC, "OAEPparams", PREFIX_XENC);

public static final QName TAG_xenc11_MGF = new QName(NS_XMLENC11, "MGF", PREFIX_XENC11);
public static final QName TAG_xenc11_KeyDerivationMethod = new QName(NS_XMLENC11, "KeyDerivationMethod", PREFIX_XENC11);

public static final String PREFIX_GHC = "ghc";
public static final QName TAG_ghc_GenericHybridCipherMethod = new QName(NS_GHC, "GenericHybridCipherMethod", PREFIX_GHC);
public static final QName TAG_ghc_KeyEncapsulationMethod = new QName(NS_GHC, "KeyEncapsulationMethod", PREFIX_GHC);
public static final QName TAG_ghc_DataEncapsulationMethod = new QName(NS_GHC, "DataEncapsulationMethod", PREFIX_GHC);
public static final QName TAG_ghc_KeyLen = new QName(NS_GHC, "KeyLen", PREFIX_GHC);

public static final String PREFIX_HKDF = "hkdf";
public static final QName TAG_hkdf_HKDFParams = new QName(NS_DSIG_MORE_2021_04, "HKDFParams", PREFIX_HKDF);
public static final QName TAG_hkdf_PRF = new QName(NS_DSIG_MORE_2021_04, "PRF", PREFIX_HKDF);
public static final QName TAG_hkdf_Salt = new QName(NS_DSIG_MORE_2021_04, "Salt", PREFIX_HKDF);
public static final QName TAG_hkdf_Info = new QName(NS_DSIG_MORE_2021_04, "Info", PREFIX_HKDF);
public static final QName TAG_hkdf_KeyLength = new QName(NS_DSIG_MORE_2021_04, "KeyLength", PREFIX_HKDF);
/** HKDF key derivation algorithm URI (RFC 9231 provisional naming pattern) */
public static final String NS_HKDF = NS_DSIG_MORE_2021_04 + "hkdf";

public static final String PREFIX_DSIG = "dsig";
public static final String PREFIX_DSIG_MORE_PSS = "pss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public class XMLSecurityProperties {
private String encryptionKeyTransportDigestAlgorithm;
private String encryptionKeyTransportMGFAlgorithm;
private byte[] encryptionKeyTransportOAEPParams;
// Generic Hybrid Cipher (W3C xmlsec-generic-hybrid) KEM-based key transport, e.g. ML-KEM (SANTUARIO-633).
// Used when encryptionKeyTransportAlgorithm is EncryptionConstants.ALGO_ID_KEYTRANSPORT_GENERIC_HYBRID.
private String encryptionKeyEncapsulationAlgorithm;
private String encryptionDataEncapsulationAlgorithm;
private String encryptionKeyEncapsulationHmacAlgorithm;
private final List<SecurePart> encryptionParts = new LinkedList<>();
private Key encryptionKey;
private Key encryptionTransportKey;
Expand Down Expand Up @@ -100,6 +105,9 @@ protected XMLSecurityProperties(XMLSecurityProperties xmlSecurityProperties) {
this.encryptionKeyTransportDigestAlgorithm = xmlSecurityProperties.encryptionKeyTransportDigestAlgorithm;
this.encryptionKeyTransportMGFAlgorithm = xmlSecurityProperties.encryptionKeyTransportMGFAlgorithm;
this.encryptionKeyTransportOAEPParams = xmlSecurityProperties.encryptionKeyTransportOAEPParams;
this.encryptionKeyEncapsulationAlgorithm = xmlSecurityProperties.encryptionKeyEncapsulationAlgorithm;
this.encryptionDataEncapsulationAlgorithm = xmlSecurityProperties.encryptionDataEncapsulationAlgorithm;
this.encryptionKeyEncapsulationHmacAlgorithm = xmlSecurityProperties.encryptionKeyEncapsulationHmacAlgorithm;
this.encryptionParts.addAll(xmlSecurityProperties.encryptionParts);
this.encryptionKey = xmlSecurityProperties.encryptionKey;
this.encryptionTransportKey = xmlSecurityProperties.encryptionTransportKey;
Expand Down Expand Up @@ -333,6 +341,43 @@ public void setEncryptionKeyTransportOAEPParams(byte[] encryptionKeyTransportOAE
this.encryptionKeyTransportOAEPParams = encryptionKeyTransportOAEPParams;
}

/**
* Returns the Key Encapsulation Method algorithm URI (e.g. an ML-KEM algorithm URI) used when
* {@link #getEncryptionKeyTransportAlgorithm()} is the Generic Hybrid Cipher algorithm
* (see {@code EncryptionConstants.ALGO_ID_KEYTRANSPORT_GENERIC_HYBRID}, SANTUARIO-633).
*/
public String getEncryptionKeyEncapsulationAlgorithm() {
return encryptionKeyEncapsulationAlgorithm;
}

public void setEncryptionKeyEncapsulationAlgorithm(String encryptionKeyEncapsulationAlgorithm) {
this.encryptionKeyEncapsulationAlgorithm = encryptionKeyEncapsulationAlgorithm;
}

/**
* Returns the Data Encapsulation Method algorithm URI (an AES-KeyWrap algorithm) used when
* {@link #getEncryptionKeyTransportAlgorithm()} is the Generic Hybrid Cipher algorithm.
*/
public String getEncryptionDataEncapsulationAlgorithm() {
return encryptionDataEncapsulationAlgorithm;
}

public void setEncryptionDataEncapsulationAlgorithm(String encryptionDataEncapsulationAlgorithm) {
this.encryptionDataEncapsulationAlgorithm = encryptionDataEncapsulationAlgorithm;
}

/**
* Returns the HMAC hash algorithm URI used as the HKDF PRF when deriving the data-encapsulation
* (AES-KeyWrap) key from the KEM shared secret. Defaults to HMAC-SHA256 if unset.
*/
public String getEncryptionKeyEncapsulationHmacAlgorithm() {
return encryptionKeyEncapsulationHmacAlgorithm;
}

public void setEncryptionKeyEncapsulationHmacAlgorithm(String encryptionKeyEncapsulationHmacAlgorithm) {
this.encryptionKeyEncapsulationHmacAlgorithm = encryptionKeyEncapsulationHmacAlgorithm;
}

public X509Certificate getEncryptionUseThisCertificate() {
return encryptionUseThisCertificate;
}
Expand Down
Loading
Loading