Я пытаюсь преобразовать открытый ключ Ed25519 в открытый ключ x25519 на Java, используя пакет lazysodium:
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import com.goterl.lazysodium.LazySodium;
import com.goterl.lazysodium.LazySodiumJava;
import com.goterl.lazysodium.SodiumJava;
public class KeyOps {
public static PublicKey ed25519ToX25519(PublicKey ed25519PublicKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
byte[] x25519PublicKeyBytes = new byte[32];
LazySodium lazySodium = new LazySodiumJava(new SodiumJava());
byte[] ed25519PublicKeyBytes = new byte[32];
System.arraycopy(ed25519PublicKey.getEncoded(), 12, ed25519PublicKeyBytes, 0, 32);
lazySodium.convertPublicKeyEd25519ToCurve25519(x25519PublicKeyBytes, ed25519PublicKeyBytes);
return KeyFactory.getInstance("X25519", "BC").generatePublic(new X509EncodedKeySpec(x25519PublicKeyBytes));
}
}
... где ed25519PublicKey
будет генерироваться следующим образом:
KeyPair keyPair = KeyPairGenerator.getInstance("Ed25519", "BC").generateKeyPair();
PublicKey ed25519PublicKey = keyPair.getPublic();
Однако я получаю случайные ошибки, как одна из следующих:
An exception occured while executing the Java class. encoded key spec not recognized: failed to construct sequence from byte[]: Extra data detected in stream
or
An exception occured while executing the Java class. encoded key spec not recognized: failed to construct sequence from byte[]: corrupted stream - out of bounds length found: 57 >= 54
(57
и 54
могут быть другими значениями)
Могу я узнать, что здесь не так? Как мне конвертировать Ed25519 pk в x25519 pk и конвертировать его обратно в формат PublicKey
?
Хорошо, я понял это.
Я понятия не имею, как закодировать X25519 pk с помощью X509EncodedKeySpec на Java, поэтому я создаю его вручную...
public static PublicKey ed25519ToX25519(PublicKey ed25519PublicKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
byte[] x25519PublicKeyBytes = new byte[32];
LazySodium lazySodium = new LazySodiumJava(new SodiumJava());
byte[] ed25519PublicKeyBytes = new byte[32];
System.arraycopy(ed25519PublicKey.getEncoded(), 12, ed25519PublicKeyBytes, 0, 32);
boolean conversion_success = lazySodium.convertPublicKeyEd25519ToCurve25519(x25519PublicKeyBytes, ed25519PublicKeyBytes);
if (!conversion_success) {
System.out.println("Conversion failed!");
System.exit(1);
}
byte[] x509Header = new byte[]{
0x30, 0x2a, // SEQUENCE, length 42
0x30, 0x05, // SEQUENCE, length 5
0x06, 0x03, 0x2b, 0x65, 0x6e, // OID for X25519
0x03, 0x21, 0x00 // BIT STRING, length 33
};
// Combine the header and the key bytes
byte[] x509EncodedKey = new byte[x509Header.length + x25519PublicKeyBytes.length];
System.arraycopy(x509Header, 0, x509EncodedKey, 0, x509Header.length);
System.arraycopy(x25519PublicKeyBytes, 0, x509EncodedKey, x509Header.length, x25519PublicKeyBytes.length);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(x509EncodedKey);
KeyFactory keyFactory = KeyFactory.getInstance("X25519");
PublicKey x25519PublicKey = keyFactory.generatePublic(keySpec);
return x25519PublicKey;
}