/*
* 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.sshd.common.util.security.eddsa;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import net.i2p.crypto.eddsa.EdDSAEngine;
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.util.test.BaseTestSupport;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class EDDSAProviderTest extends BaseTestSupport {
private static KeyPair keyPair;
public EDDSAProviderTest() {
super();
}
@BeforeClass
public static void checkProviderSupported() throws GeneralSecurityException {
Assume.assumeTrue(SecurityUtils.EDDSA + " not supported", SecurityUtils.isEDDSACurveSupported());
KeyPairGenerator g = SecurityUtils.getKeyPairGenerator(SecurityUtils.EDDSA);
assertNotNull("No generator instance", g);
keyPair = g.generateKeyPair();
assertNotNull("No key pair generated", keyPair);
PublicKey pubKey = keyPair.getPublic();
assertNotNull("No public key", pubKey);
assertEquals("Mismatched public key algorithm", SecurityUtils.EDDSA, pubKey.getAlgorithm());
assertEquals("Mismatched public key type", KeyPairProvider.SSH_ED25519, KeyUtils.getKeyType(pubKey));
PrivateKey prvKey = keyPair.getPrivate();
assertNotNull("No private key", prvKey);
assertEquals("Mismatched key-pair algorithm", pubKey.getAlgorithm(), prvKey.getAlgorithm());
assertEquals("Mismatched private key type", KeyPairProvider.SSH_ED25519, KeyUtils.getKeyType(prvKey));
}
@Test
public void testSignature() throws GeneralSecurityException {
Signature s = SecurityUtils.getSignature(EdDSAEngine.SIGNATURE_ALGORITHM);
assertNotNull("No signature instance", s);
s.initSign(keyPair.getPrivate());
byte[] data = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
s.update(data);
byte[] signed = s.sign();
s = SecurityUtils.getSignature(EdDSAEngine.SIGNATURE_ALGORITHM);
s.initVerify(keyPair.getPublic());
s.update(data);
assertTrue("Failed to verify", s.verify(signed));
}
@Test
public void testPublicKeyEntryDecoder() throws IOException, GeneralSecurityException {
String comment = getCurrentTestName() + "@" + getClass().getSimpleName();
String expected = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGPKSUTyz1HwHReFVvD5obVsALAgJRNarH4TRpNePnAS " + comment;
AuthorizedKeyEntry keyEntry = AuthorizedKeyEntry.parseAuthorizedKeyEntry(expected);
assertNotNull("No extracted key entry", keyEntry);
assertEquals("Mismatched key type", KeyPairProvider.SSH_ED25519, keyEntry.getKeyType());
assertEquals("Mismatched comment", comment, keyEntry.getComment());
StringBuilder sb = new StringBuilder(expected.length());
PublicKey pubKey = keyEntry.appendPublicKey(sb, null);
assertEquals("Mismatched encoded result", expected, sb.toString());
testPublicKeyRecovery(pubKey);
}
@Test
public void testGeneratedPublicKeyRecovery() throws IOException, GeneralSecurityException {
testPublicKeyRecovery(keyPair.getPublic());
}
private void testPublicKeyRecovery(PublicKey pubKey) throws IOException, GeneralSecurityException {
assertNotNull("No public key generated", pubKey);
assertEquals("Mismatched public key algorithm", SecurityUtils.EDDSA, pubKey.getAlgorithm());
Buffer buf = SecurityUtils.putRawEDDSAPublicKey(new ByteArrayBuffer(), pubKey);
PublicKey actual = buf.getRawPublicKey();
assertEquals("Mismatched key algorithm", pubKey.getAlgorithm(), actual.getAlgorithm());
assertEquals("Mismatched recovered key", pubKey, actual);
}
}