BCECPublicKey a la huella digital

Ene Wytze:

Cuando se conecta a un "nuevo" servidor SSH, con la línea de comandos, se mostrará una huella digital:

La autenticidad de anfitrión 'test.com (0.0.0.0)' no puede ser establecida.
ECDSA huella de la clave es SHA256: 566gJgmcB43EXimrT0exEKfxSd3xc7RBS6EPx1XZwYc.
¿Seguro que desea continuar conexión (sí / no)?

Yo entiendo que la huella digital es una cadena de base 64 del hash SHA256 de la clave pública.

Sé cómo generar esta huella digital con un RSAPublicKey:

    RSAPublicKey publicKey = ...;

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

    dataOutputStream.writeInt("ssh-rsa".getBytes().length);
    dataOutputStream.write("ssh-rsa".getBytes());
    dataOutputStream.writeInt(publicKey.getPublicExponent().toByteArray().length);
    dataOutputStream.write(publicKey.getPublicExponent().toByteArray());
    dataOutputStream.writeInt(publicKey.getModulus().toByteArray().length);
    dataOutputStream.write(publicKey.getModulus().toByteArray());

    MessageDigest digest = MessageDigest.getInstance("SHA256");
    byte[] result = digest.digest(byteArrayOutputStream.toByteArray());

    String fingerprint = Base64.getEncoder().encodeToString(result);

Pero ¿cómo puedo hacer esto con una BCECPublicKey?

ACTUALIZACIÓN
descubrí que el BCECPublicKeyno es similar a RSAPublicKeyen absoluto. No sabía que la clave pública del servidor SSH es ECDSA y la clave pública RSA es cliente.

También la forma en que los bytes están estructurados es la manera diferente. La clave pública RSA comienza con una cabecera ( ssh-rsa). La longitud de la cabecera se puede leer en los primeros 4 bytes ( readInt()). Pero cuando hago esto con el ECDSA la longitud es hasta long para representar una cabecera ...

Además de la respuesta
Algo para copiar y pegar:

    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);

    MessageDigest digest = MessageDigest.getInstance("SHA256");
    byte[] result = digest.digest(byteArrayOutputStream.toByteArray());

    String fingerprint = Base64.getEncoder().encodeToString(result);
dave_thompson_085:

El formato OpenSSH publickey (y el formato de alambre de SSH en el que se basa) hace comienzan con el tipo, pero para el tipo ECDSA incluye el ID de la curva. A modo de ejemplo, uno de mis sistemas de prueba tiene una clave ECDSA / P256 de la siguiente manera:

$ awk '{print $2}' <id_ecdsa.pub |openssl base64 -d -A |xxd
0000000: 0000 0013 6563 6473 612d 7368 6132 2d6e  ....ecdsa-sha2-n
0000010: 6973 7470 3235 3600 0000 086e 6973 7470  istp256....nistp
0000020: 3235 3600 0000 4104 8141 9c28 53e7 532e  256...A..A.(S.S.
0000030: 8c4b 9781 c6a5 1820 f41a bc95 4e62 13a9  .K..... ....Nb..
0000040: 8356 a517 be55 6ebc fbf4 de74 e216 8f17  .V...Un....t....
0000050: 6222 011c 5920 a3fc caed c880 4298 46d5  b"..Y ......B.F.
0000060: dd39 396e d72d 1e40                      .99n.-.@

Que consiste en:
4 bytes 00000013 int bigEndian = 19: longitud del tipo
19 bytes 'ECDSA-SHA2-nistp256' tipo
4 bytes 00000008 int bigEndian = 8: longitud de curveid
8 bytes 'nistp256' curveid (redundante, pero eso es el formato de alambre )
4 bytes 00000041 int bigEndian = 65: longitud del punto pub
65 bytes a partir de 04: punto pub en formato X9.62, copiado más convenientemente en SEC1, que es 1 byte 04 = sin comprimir, N bytes coordenada X, N bytes Y- coordinar donde N es el tamaño (fijo) necesaria para representar campo subyacente de la curva como sin signo.

Estos se definen principalmente en la sección 3.1 rfc5656 y la curveid es de 6.1. El RFC permite comprimido formato de coma, pero OpenSSH no utiliza esa opción.

BCECPublicKey.getEncoded()(como todas las clases de Java PublicKey) devuelve una llamada codificación X.509 (realmente SubjectPublicKeyInfo, SPKI), que para la CE incluye el punto X9.62 pública en formato no comprimido, pero se necesita un poco de análisis sintáctico para extraerlo. Puesto que usted tiene antes de Cristo, es más fácil de usar que:

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

Alternativamente .getW()y .getQ()obtener el punto como una clase JCE o BC, desde cualquiera de los cuales se puede obtener el (afín) coordenadas X e Y como BigIntegerresp. ECFieldElementque en los rendimientos de giro BigInteger, y cada uno BigIntegerse puede convertir en una de tamaño variable matriz de bytes que se debe o-truncado izquierda y luego la almohadilla de izquierda al tamaño correcto.

El resultado es que los datos hash. En caso de que no saben, sólo las versiones de OpenSSH 6.8 utilizar hasta base 64 (SHA256 (pubkey)) de la huella dactilar (por defecto). Antes de que se trataba hexagonal con puntos y comas (MD5 (pubkey)), y las versiones más recientes puede hacer la vieja huella digital para la compatibilidad (véase la opción FingerprintHashde ssh_configpara sshy la bandera -Ede ssh-keygen).

Y para ser claro que esto es sólo el OpenSSH huella digital. Huellas dactilares clave también se utilizan en el PGP y X.509 / PKIX (SSL / TLS, CMS / SMIME, etc) y mundos que son totalmente diferentes.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=175900&siteId=1
Recomendado
Clasificación