package org.xbib.net.security.test;

import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.interfaces.EdECPublicKey;
import java.security.spec.X509EncodedKeySpec;
import org.junit.jupiter.api.Test;
import org.xbib.net.security.eddsa.EdDSAPublicKey;
import org.xbib.net.security.eddsa.Utils;
import org.xbib.net.security.util.HexUtil;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class Ed25519KeyTest {

    @Test
    public void generate() throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
        KeyPair kp = kpg.generateKeyPair();
        Signature sig = Signature.getInstance("Ed25519");
        sig.initSign(kp.getPrivate());
        sig.update("Hello Jörg".getBytes(StandardCharsets.UTF_8));
        byte[] s = sig.sign();
        sig.initVerify(kp.getPublic());
        sig.update("Hello Jörg".getBytes(StandardCharsets.UTF_8));
        assertTrue(sig.verify(s));
    }

    @Test
    public void testPublicKeyPayload() throws Exception {
        String TEST_KEY = "302a300506032b65700321007d3691f280f8c8e7be7380e12bf6004a380c13d8fc1d7fed14aef4f301e4ca36";
        X509EncodedKeySpec encoded = new X509EncodedKeySpec(Utils.hexToBytes(TEST_KEY));
        EdDSAPublicKey key = new EdDSAPublicKey(encoded);
        assertEquals("7d3691f280f8c8e7be7380e12bf6004a380c13d8fc1d7fed14aef4f301e4ca36", HexUtil.toHex(key.getAbyte()));
        java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("EdDSA");
        EdECPublicKey edECPublicKey = (EdECPublicKey) keyFactory.generatePublic(encoded);
        byte[] b = edECPublicKey.getPoint().getY().toByteArray();
        reverse(b);
        if (edECPublicKey.getPoint().isXOdd()) {
            b[b.length - 1] |= (byte) 0x80;
        }
        assertEquals("7d3691f280f8c8e7be7380e12bf6004a380c13d8fc1d7fed14aef4f301e4ca36", HexUtil.toHex(b));
    }

    private static void reverse(byte [] arr) {
        int i = 0;
        int j = arr.length - 1;
        while (i < j) {
            swap(arr, i, j);
            i++;
            j--;
        }
    }

    private static void swap(byte[] arr, int i, int j) {
        byte tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}
