OpenSSH ecdsa для BCECPublicKey - PullRequest
       33

OpenSSH ecdsa для BCECPublicKey

0 голосов
/ 18 декабря 2018

Я хотел бы преобразовать строку открытого ключа ecdsa OpenSSH (файл .pub) в экземпляр BCECPublicKey.

Что я хочу добиться, это обратный код:

BCECPublicKey publicKey = ...;

byte[] point = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(publicKey.getEncoded())).getPublicKeyData().getOctets();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);

dataOutputStream.writeInt("ecdsa-sha2-nistp256".getBytes().length);
dataOutputStream.write("ecdsa-sha2-nistp256".getBytes());
dataOutputStream.writeInt("nistp256".getBytes().length);
dataOutputStream.write("nistp256".getBytes());
dataOutputStream.writeInt(point.length);
dataOutputStream.write(point);

String base64 = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());

Вот что я попробовал:

    // Valid ecdsa-sha2-nistp256 public key string from a .pub file.
    String base64 = "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBG93uDMAjwxpPFXgLFFs7FzWZXrQRaXnBMqmHaRN/5JRzljuqYAUAkW98HvFxGKrnb2JdW3X785AxLNzVhiiw+4=";
    byte[] bytes = Base64.getDecoder().decode(base64);
    ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");

    // java.lang.IllegalArgumentException: Incorrect length for infinity encoding
    ECPoint point = ecSpec.getCurve().decodePoint(bytes);
    ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(point, ecSpec);
    KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC");
    PublicKey pk = keyFactory.generatePublic(publicKeySpec);

Но, похоже, это не сработало.

Есть ли простой способ сделать это с надувным замком?

1 Ответ

0 голосов
/ 19 декабря 2018

Вы знаете, что создали BLOB-объект, объединив шесть вещей, только шестая из которых была фактической кодировкой точек, так как же вы могли бы представить, что использование всего двоичного объекта в качестве точечного кодирования будет правильным?

Чистый и надежный способ - разобрать блоб обратно на его части и извлечь кодировку точек;грязный способ - просто предположить, что большой двоичный объект, как и ожидалось, предназначен для ecdsa-sha2-nistp256 (и без сжатия), поэтому последние 65 байтов являются точечной кодировкой:

String base64 = "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBG93uDMAjwxpPFXgLFFs7FzWZXrQRaXnBMqmHaRN/5JRzljuqYAUAkW98HvFxGKrnb2JdW3X785AxLNzVhiiw+4=";
byte[] bytes = Base64.getDecoder().decode(base64), temp;

if( clean ){
    DataInputStream instr = new DataInputStream (new ByteArrayInputStream (bytes));
    temp = new byte[instr.readInt()]; instr.read(temp);
    if( !Arrays.equals(temp,"ecdsa-sha2-nistp256".getBytes())) throw new Exception ("bad key");
    temp = new byte[instr.readInt()]; instr.read(temp);
    if( !Arrays.equals(temp,"nistp256".getBytes())) throw new Exception ("bad key");
    temp = new byte[instr.readInt()]; instr.read (temp);
}else{
    temp = Arrays.copyOfRange(bytes, bytes.length-65, bytes.length);
}
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec ("secp256r1");
org.bouncycastle.math.ec.ECPoint point = ecSpec.getCurve().decodePoint (temp);
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC");
PublicKey pk = keyFactory.generatePublic(new org.bouncycastle.jce.spec.ECPublicKeySpec(point, ecSpec));
...