diff --git a/src/addons/hwtoken/src/main/java/ee/ria/xroad/signer/tokenmanager/token/helper/KeyPairHelper.java b/src/addons/hwtoken/src/main/java/ee/ria/xroad/signer/tokenmanager/token/helper/KeyPairHelper.java index 1499420bf0..0cd8127433 100644 --- a/src/addons/hwtoken/src/main/java/ee/ria/xroad/signer/tokenmanager/token/helper/KeyPairHelper.java +++ b/src/addons/hwtoken/src/main/java/ee/ria/xroad/signer/tokenmanager/token/helper/KeyPairHelper.java @@ -46,6 +46,7 @@ static KeyPairHelper of(KeyAlgorithm algorithm) { return switch (algorithm) { case RSA -> RsaKeyPairHelper.INSTANCE; case EC -> EcKeyPairHelper.INSTANCE; + case EdDSA -> null; //TODO #EDDSA proper impl }; } } diff --git a/src/central-server/admin-service/globalconf-generator/src/main/java/org/niis/xroad/cs/admin/globalconf/generator/DirectoryContentSigner.java b/src/central-server/admin-service/globalconf-generator/src/main/java/org/niis/xroad/cs/admin/globalconf/generator/DirectoryContentSigner.java index 4218e0a02a..67d6612340 100644 --- a/src/central-server/admin-service/globalconf-generator/src/main/java/org/niis/xroad/cs/admin/globalconf/generator/DirectoryContentSigner.java +++ b/src/central-server/admin-service/globalconf-generator/src/main/java/org/niis/xroad/cs/admin/globalconf/generator/DirectoryContentSigner.java @@ -78,7 +78,7 @@ private byte[] sign(String keyId, byte[] data) { var signatureAlgorithmId = getSignAlgorithmId(keyId, signDigestAlgorithmId); - byte[] digest = calculateDigest(signatureAlgorithmId.digest(), data); + byte[] digest = signatureAlgorithmId.prehashable() ? calculateDigest(signatureAlgorithmId.digest(), data) : data; return Signatures.useAsn1DerFormat(signatureAlgorithmId, signerProxy.sign(keyId, signatureAlgorithmId, digest)); } diff --git a/src/central-server/admin-service/infra-api-rest/src/main/java/org/niis/xroad/cs/admin/rest/api/mapper/ConfigurationSigningKeyDtoMapper.java b/src/central-server/admin-service/infra-api-rest/src/main/java/org/niis/xroad/cs/admin/rest/api/mapper/ConfigurationSigningKeyDtoMapper.java index 63ead04ef3..ae5f0e9f01 100644 --- a/src/central-server/admin-service/infra-api-rest/src/main/java/org/niis/xroad/cs/admin/rest/api/mapper/ConfigurationSigningKeyDtoMapper.java +++ b/src/central-server/admin-service/infra-api-rest/src/main/java/org/niis/xroad/cs/admin/rest/api/mapper/ConfigurationSigningKeyDtoMapper.java @@ -26,12 +26,15 @@ */ package org.niis.xroad.cs.admin.rest.api.mapper; +import ee.ria.xroad.common.crypto.identifier.KeyAlgorithm; + import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingConstants; import org.niis.xroad.cs.admin.api.converter.GenericUniDirectionalMapper; import org.niis.xroad.cs.admin.api.domain.ConfigurationSigningKeyWithDetails; import org.niis.xroad.cs.openapi.model.ConfigurationSigningKeyDto; +import org.niis.xroad.cs.openapi.model.KeyAlgorithmDto; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface ConfigurationSigningKeyDtoMapper extends @@ -46,4 +49,12 @@ public interface ConfigurationSigningKeyDtoMapper extends @Mapping(target = "keyHash", ignore = true) ConfigurationSigningKeyDto toTarget(ConfigurationSigningKeyWithDetails model); + default KeyAlgorithmDto toTarget(KeyAlgorithm model) { + return switch (model){ + case RSA -> KeyAlgorithmDto.RSA; + case EC -> KeyAlgorithmDto.EC; + case EdDSA -> KeyAlgorithmDto.ED_DSA; + }; + } + } diff --git a/src/central-server/openapi-model/src/main/resources/openapi-definition.yaml b/src/central-server/openapi-model/src/main/resources/openapi-definition.yaml index 7c1a888ecc..8409704058 100644 --- a/src/central-server/openapi-model/src/main/resources/openapi-definition.yaml +++ b/src/central-server/openapi-model/src/main/resources/openapi-definition.yaml @@ -3630,6 +3630,7 @@ components: enum: - RSA - EC + - EdDSA example: RSA format: enum type: string diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/EdDsaKeyManager.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/EdDsaKeyManager.java new file mode 100644 index 0000000000..972bdcceb8 --- /dev/null +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/EdDsaKeyManager.java @@ -0,0 +1,74 @@ +/* + * The MIT License + * Copyright (c) 2018 Estonian Information System Authority (RIA), + * Nordic Institute for Interoperability Solutions (NIIS), Population Register Centre (VRK) + * Copyright (c) 2015-2017 Estonian Information System Authority (RIA), Population Register Centre (VRK) + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package ee.ria.xroad.common.crypto; + +import ee.ria.xroad.common.crypto.identifier.KeyAlgorithm; +import ee.ria.xroad.common.crypto.identifier.SignAlgorithm; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.RSAPublicKeySpec; + +public final class EdDsaKeyManager extends AbstractKeyManager { + + // Use no digesting algorithm, since the input data is already a digest + private static final SignAlgorithm SIGNATURE_ALGORITHM = SignAlgorithm.ofName("Ed25519"); + private static final KeyAlgorithm CRYPTO_ALGORITHM = KeyAlgorithm.EdDSA; + + EdDsaKeyManager() { + super(CRYPTO_ALGORITHM); + } + + /** + * Generates X509 encoded public key bytes from a given modulus and + * public exponent. + * @param modulus the modulus + * @param publicExponent the public exponent + * @return generated public key bytes + * @throws Exception if any errors occur + */ + public byte[] generateX509PublicKey(BigInteger modulus, BigInteger publicExponent) throws Exception { + RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); + return generateX509PublicKey(rsaPublicKeySpec); + } + + @Override + public SignAlgorithm getSoftwareTokenSignAlgorithm() { + return SIGNATURE_ALGORITHM; + } + + @Override + public SignAlgorithm getSoftwareTokenKeySignAlgorithm() { + return SignAlgorithm.ED25519; + } + + @Override + public KeyPair generateKeyPair() throws Exception { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(SignAlgorithm.ED25519.name()); + + return keyPairGen.generateKeyPair(); + } +} diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/KeyManagers.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/KeyManagers.java index e3419a4cb9..5879b47f5a 100644 --- a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/KeyManagers.java +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/KeyManagers.java @@ -34,7 +34,8 @@ public final class KeyManagers { private static final Map BY_TYPE = Map.of( KeyAlgorithm.RSA, new RsaKeyManager(), - KeyAlgorithm.EC, new EcKeyManager() + KeyAlgorithm.EC, new EcKeyManager(), + KeyAlgorithm.EdDSA, new EdDsaKeyManager() ); public static KeyManager getFor(String keyAlgorithm) { diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/SignDataPreparer.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/SignDataPreparer.java index c3c04cc92a..360d7b6994 100644 --- a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/SignDataPreparer.java +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/SignDataPreparer.java @@ -36,7 +36,7 @@ public sealed interface SignDataPreparer { static SignDataPreparer of(SignAlgorithm algorithm) { return switch (algorithm.signMechanism()) { case CKM_RSA_PKCS -> RsaPkcsPreparer.INSTANCE; - case CKM_RSA_PKCS_PSS, CKM_ECDSA -> NoopPreparer.INSTANCE; + case CKM_RSA_PKCS_PSS, CKM_ECDSA, CKM_EDDSA -> NoopPreparer.INSTANCE; }; } diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/KeyAlgorithm.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/KeyAlgorithm.java index a14cfd1346..a8c3751868 100644 --- a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/KeyAlgorithm.java +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/KeyAlgorithm.java @@ -25,5 +25,7 @@ package ee.ria.xroad.common.crypto.identifier; public enum KeyAlgorithm { - RSA, EC + RSA, EC, EdDSA + /* TODO #EDDSA probably better just have 2 different types for Es25519 and Ed448, + even java KeyPairGenerator takes specific name and not general type code as for EC/RSA */ } diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignAlgorithm.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignAlgorithm.java index 89f81a3f84..97907de4a5 100644 --- a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignAlgorithm.java +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignAlgorithm.java @@ -38,6 +38,7 @@ import static ee.ria.xroad.common.crypto.identifier.DigestAlgorithm.SHA384; import static ee.ria.xroad.common.crypto.identifier.DigestAlgorithm.SHA512; import static ee.ria.xroad.common.crypto.identifier.SignMechanism.CKM_ECDSA; +import static ee.ria.xroad.common.crypto.identifier.SignMechanism.CKM_EDDSA; import static ee.ria.xroad.common.crypto.identifier.SignMechanism.CKM_RSA_PKCS; import static ee.ria.xroad.common.crypto.identifier.SignMechanism.CKM_RSA_PKCS_PSS; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA1; @@ -45,6 +46,7 @@ import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA384; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA512; +import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED25519; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256; import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1; @@ -75,6 +77,8 @@ public sealed interface SignAlgorithm { SignAlgorithm SHA384_WITH_ECDSA = INDEX.create("SHA384withECDSA", ALGO_ID_SIGNATURE_ECDSA_SHA384, CKM_ECDSA, SHA384); SignAlgorithm SHA512_WITH_ECDSA = INDEX.create("SHA512withECDSA", ALGO_ID_SIGNATURE_ECDSA_SHA512, CKM_ECDSA, SHA512); + SignAlgorithm ED25519 = INDEX.create("Ed25519", ALGO_ID_SIGNATURE_EDDSA_ED25519, CKM_EDDSA, null); + String name(); String uri(); @@ -87,6 +91,10 @@ default KeyAlgorithm algorithm() { SignMechanism signMechanism(); + default boolean prehashable(){ + return digest() != null; + } + static SignAlgorithm ofUri(String uri) { return INDEX.ofUri(uri).orElseGet(() -> new UnknownSignAlgorithm(null, uri)); } @@ -177,6 +185,9 @@ private Optional ofName(String name) { } private Optional ofDigestAndSignMechanism(DigestAlgorithm algorithm, SignMechanism mechanism) { + if(CKM_EDDSA.equals(mechanism)){ + return Optional.of(SignAlgorithm.ED25519); + } return Optional.ofNullable(byDigestAndMechanism.get(new Key(algorithm, mechanism))); } diff --git a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignMechanism.java b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignMechanism.java index b58676edb3..d9e5aa8d22 100644 --- a/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignMechanism.java +++ b/src/common/common-core/src/main/java/ee/ria/xroad/common/crypto/identifier/SignMechanism.java @@ -27,7 +27,8 @@ public enum SignMechanism { CKM_RSA_PKCS(KeyAlgorithm.RSA), CKM_RSA_PKCS_PSS(KeyAlgorithm.RSA), - CKM_ECDSA(KeyAlgorithm.EC); + CKM_ECDSA(KeyAlgorithm.EC), + CKM_EDDSA(KeyAlgorithm.EdDSA); private final KeyAlgorithm algorithm; diff --git a/src/security-server/admin-service/application/src/main/java/org/niis/xroad/securityserver/restapi/converter/KeyConverter.java b/src/security-server/admin-service/application/src/main/java/org/niis/xroad/securityserver/restapi/converter/KeyConverter.java index a83d9b1c05..09419ec198 100644 --- a/src/security-server/admin-service/application/src/main/java/org/niis/xroad/securityserver/restapi/converter/KeyConverter.java +++ b/src/security-server/admin-service/application/src/main/java/org/niis/xroad/securityserver/restapi/converter/KeyConverter.java @@ -116,6 +116,7 @@ private KeyAlgorithm mapKeyAlgorithm(String signMechanismName) { return switch (SignMechanism.valueOf(signMechanismName).keyAlgorithm()) { case RSA -> KeyAlgorithm.RSA; case EC -> KeyAlgorithm.EC; + case EdDSA -> KeyAlgorithm.ED_DSA; //TODO #EDDSA proper impl }; } diff --git a/src/security-server/openapi-model/src/main/resources/META-INF/openapi-definition.yaml b/src/security-server/openapi-model/src/main/resources/META-INF/openapi-definition.yaml index a2bf2d0a8c..3ff09eccba 100644 --- a/src/security-server/openapi-model/src/main/resources/META-INF/openapi-definition.yaml +++ b/src/security-server/openapi-model/src/main/resources/META-INF/openapi-definition.yaml @@ -6741,6 +6741,7 @@ components: enum: - RSA - EC + - EdDSA example: RSA format: enum type: string diff --git a/src/signer-protocol/src/main/proto/key_service.proto b/src/signer-protocol/src/main/proto/key_service.proto index 42dd3201d0..094d13299a 100644 --- a/src/signer-protocol/src/main/proto/key_service.proto +++ b/src/signer-protocol/src/main/proto/key_service.proto @@ -55,6 +55,7 @@ enum Algorithm { ALGORITHM_UNKNOWN = 0; RSA = 1; EC = 2; + EdDSA = 3; } message GetKeyIdForCertHashReq { diff --git a/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerParallelStepDefs.java b/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerParallelStepDefs.java index 5c5bfd0758..e50bbacd73 100644 --- a/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerParallelStepDefs.java +++ b/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerParallelStepDefs.java @@ -59,6 +59,7 @@ public void digestCanBeSignedUsingKeyFromToken(String keyName, String friendlyNa var signAlgorithm = switch (SignMechanism.valueOf(key.getSignMechanismName()).keyAlgorithm()) { case RSA -> SHA256_WITH_RSA; case EC -> SHA256_WITH_ECDSA; + case EdDSA -> null; //TODO #EDDSA proper impl }; doConcurrentSign(() -> { diff --git a/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerStepDefs.java b/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerStepDefs.java index 67dabaa8a3..6a4909b469 100644 --- a/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerStepDefs.java +++ b/src/signer/core/src/intTest/java/org/niis/xroad/signer/test/glue/SignerStepDefs.java @@ -417,6 +417,7 @@ public void digestCanBeSignedUsingKeyFromToken(String keyName, String friendlyNa var signAlgorithm = switch (SignMechanism.valueOf(key.getSignMechanismName()).keyAlgorithm()) { case RSA -> SHA256_WITH_RSA; case EC -> SHA256_WITH_ECDSA; + case EdDSA -> null; //TODO #EDDSA proper impl }; SignerProxy.sign(key.getId(), signAlgorithm, calculateDigest(SHA256, digest.getBytes(UTF_8))); @@ -454,6 +455,7 @@ public void certificateCanBeSignedUsingKeyFromToken(String keyName, String frien var signAlgorithm = switch (algorithm) { case RSA -> SHA256_WITH_RSA; case EC -> SHA256_WITH_ECDSA; + case EdDSA -> null; //TODO #EDDSA proper impl }; final byte[] bytes = SignerProxy.signCertificate(key.getId(), signAlgorithm, "CN=CS", publicKey); @@ -471,6 +473,7 @@ public void sign(String keyName, String friendlyName) throws Exception { var signAlgorithm = switch (SignMechanism.valueOf(key.getSignMechanismName()).keyAlgorithm()) { case RSA -> SHA256_WITH_RSA; case EC -> SHA256_WITH_ECDSA; + case EdDSA -> null; //TODO #EDDSA proper impl }; byte[] bytes = SignerProxy.sign(key.getId(), signAlgorithm, calculateDigest(SHA256, digest.getBytes(UTF_8))); diff --git a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/module/SoftwareModuleWorker.java b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/module/SoftwareModuleWorker.java index 20e229d558..96a72753c4 100644 --- a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/module/SoftwareModuleWorker.java +++ b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/module/SoftwareModuleWorker.java @@ -27,6 +27,7 @@ import ee.ria.xroad.common.SystemProperties; import ee.ria.xroad.common.crypto.identifier.KeyAlgorithm; +import ee.ria.xroad.common.crypto.identifier.SignMechanism; import ee.ria.xroad.signer.protocol.dto.TokenInfo; import ee.ria.xroad.signer.tokenmanager.TokenManager; import ee.ria.xroad.signer.tokenmanager.token.AbstractTokenWorker; @@ -46,7 +47,8 @@ public class SoftwareModuleWorker extends AbstractModuleWorker { private static final List TOKENS = List.of(new SoftwareTokenType( Map.of( KeyAlgorithm.EC, SystemProperties.getSofTokenEcSignMechanism(), - KeyAlgorithm.RSA, SystemProperties.getSoftTokenRsaSignMechanism() + KeyAlgorithm.RSA, SystemProperties.getSoftTokenRsaSignMechanism(), + KeyAlgorithm.EdDSA, SignMechanism.CKM_EDDSA //TODO #EDDSA proper impl ) )); diff --git a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/AbstractTokenWorker.java b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/AbstractTokenWorker.java index c1ac34da3b..44b5f56314 100644 --- a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/AbstractTokenWorker.java +++ b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/AbstractTokenWorker.java @@ -220,6 +220,7 @@ protected KeyAlgorithm mapAlgorithm(Algorithm algorithm) { return switch (algorithm) { case RSA, ALGORITHM_UNKNOWN, UNRECOGNIZED -> KeyAlgorithm.RSA; case EC -> KeyAlgorithm.EC; + case EdDSA -> KeyAlgorithm.EdDSA; }; } diff --git a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/SoftwareTokenWorker.java b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/SoftwareTokenWorker.java index 48f68063ba..1a838e5415 100644 --- a/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/SoftwareTokenWorker.java +++ b/src/signer/core/src/main/java/ee/ria/xroad/signer/tokenmanager/token/SoftwareTokenWorker.java @@ -127,7 +127,9 @@ public class SoftwareTokenWorker extends AbstractTokenWorker { SignAlgorithm.SHA1_WITH_ECDSA, SignAlgorithm.SHA256_WITH_ECDSA, SignAlgorithm.SHA384_WITH_ECDSA, - SignAlgorithm.SHA512_WITH_ECDSA + SignAlgorithm.SHA512_WITH_ECDSA, + + SignAlgorithm.ED25519 ); private static final String UNSUPPORTED_SIGN_ALGORITHM = "unsupported_sign_algorithm";