Le dimensioni sono diverse perché i formati sono diversi. Le stringhe che mostri sono entrambi valori binari codificati in Base64 . In tutto questo messaggio parlo dei valori binari, cioè suppongo che tu abbia prima decodificato le stringhe Base64 in binario.
Matematicamente, una chiave pubblica ECDSA è un punto su una curva ellittica. Un punto ha due coordinate, chiamate X e Y , che sono legate l'una all'altra attraverso l'equazione della curva (in tal caso, Y 2 = X 3 + aX + b per due costanti a e b che definiscono la curva specifica). Qui, si utilizza la curva NIST P-256, che è stata specificata per funzionare in un campo a 256 bit, cioè X e Y sono due interi a 256 bit. Lo standard ANSI X9.62 definisce un formato a 65 byte per rappresentare tale < em> X e Y ; in pratica, un primo byte di valore 0x04, seguito da X su esattamente 32 byte (nella notazione big-endian), quindi Y su altri 32 byte.
Fin qui tutto bene. Quindi sia Java che SSH eseguono il wrap di quel valore a 65 byte in una struttura che identifica anche esplicitamente la curva stessa attraverso alcuni identificatori simbolici. Lo fanno in modo diverso.
Java segue la codifica basata su ASN.1 specificata anche in ANSI X9.62. Esistono diverse opzioni, ma nel tuo caso hai un SEQUENCE
il cui contenuto è un sub-% coidato nidificato, quindi un SEQUENCE
. Il sub-% co_de nidificato contiene due valori di BIT STRING
, il primo è 1.2.840.10045.2.1 (che significa "questa è una chiave pubblica curva ellittica"), e il secondo è 1.2.840.10045.3.1.7, che indica la curva NIST P-256. I contenuti di SEQUENCE
sono, esattamente, la codifica di 65 byte del punto di curva. Per farla breve: il valore Java, quando decodificato Base64, fornisce un valore di lunghezza 91 byte, gli ultimi 65 byte di cui la codifica di X e Y .
OpenSSH, d'altra parte, è ben noto per un'allergia cronica agli standard e, naturalmente, ha inventato il proprio formato. È stato quindi documentato in RFC 5656, sezione 3.1 . Fondamentalmente, la chiave codificata consiste in tre "stringhe", una dopo l'altra. Ogni stringa consiste in un'intestazione a 32 bit (4 byte, notazione big-endian) seguita dal valore stringa; l'intestazione contiene la lunghezza del valore, in byte. La prima stringa è la codifica ASCII di "ecdsa-sha2-nistp256" (identifica l'algoritmo della firma). La seconda stringa è la codifica ASCII di "nistp256" (identifica la curva, ridondante con la prima stringa). La terza stringa ha un valore di 65 byte e, avete indovinato, questa è la codifica di 65 byte di X e Y . La lunghezza totale è di 104 byte e la codifica X e Y utilizza gli ultimi 65 di questi 104 byte.
Quindi in pratica, in entrambi i formati, la parte interessante è esattamente gli ultimi 65 byte; il resto è solo un identificatore per la curva coinvolta, in due dialetti distinti. Se generate più chiavi con OBJECT IDENTIFIER
, noterete che differiranno solo negli ultimi 65 byte (anche in questo caso, dopo decodifica Base64). Allo stesso modo con la produzione di molte chiavi in Java.
Pertanto, la conversione da una chiave pubblica prodotta da Java a una chiave pubblica compatibile con SSH è tanto semplice quanto prendere gli ultimi 65 byte di quella chiave (dopo la decodifica Base64, dove applicabile) e concatenarli dopo l'intestazione da 39 byte di una chiave SSH.