Dimensioni errate per la coppia di chiavi CE

3

Sto usando OpenSSL per generare coppie di chiavi EC. Ho notato che la lunghezza delle chiavi come visualizzata da OpenSSL è esattamente un byte più lunga del previsto per la chiave privata e pubblica.

Il 00 (primo byte della chiave privata) è un intero codificato ASN.1, assicura che il valore sia interpretato come non negativo e il primo byte della chiave pubblica 04 sia per la chiave non compressa.

La chiave privata è 33 byte (non 32 byte) e la chiave pubblica è 65 byte (non 64 byte)

Private-Key: (256 bit)

priv:

  00:b5:15:94:05:96:a0:6b:03:4e:9d:49:01:ce:50:
  71:f7:6a:fe:28:24:2a:24:23:b2:0e:d6:a0:b5:6a:
  0f:65:d3

pub:

  04:db:b4:97:f3:5d:17:45:e5:79:4f:db:c2:bd:ea:
  19:2c:fd:3a:dc:bc:19:49:91:e1:e1:59:9f:0c:7a:
  9e:e7:97:c1:ad:4c:a8:53:b6:b0:af:d8:7e:58:34:
  90:e1:d1:0b:85:9d:89:e1:4c:7c:b8:b6:2d:27:70:
  62:66:9e:b2:ac

ASN1 OID: prime256v1

NIST CURVE: P-256

Come posso cancellare il primo byte per la chiave privata e pubblica? o altrimenti, come posso regolare la dimensione del privato in 32 byte e la chiave pubblica in 64 byte?

Il leader 00 cambia il valore del numero?

Sto usando OpenSSL 1.0.2k 26 gennaio 2017

    
posta Med 26.06.2017 - 16:17
fonte

1 risposta

3

Non sono sicuro del motivo per cui vuoi tagliare i byte. Quindi non sono sicuro che questa sia una buona risposta alla tua domanda qui va comunque.

Ecco cosa ho scoperto leggendo le RFC / sperimentando.

How can I adjust the size of the private to 32 Bytes and public key to 64 Bytes?

Non devi. Sono già in quella forma. È solo un po 'di confusione leggere dalla stampa di openssl.

Does the leading 00 change the value of the number?

La risposta è "No" se lo si analizzasse comunque come unsigned int. (E "sì" se tu fossi (erroneamente) andando ad analizzarlo come int firmato. In tal caso devi mantenere il prefisso 0x00.)

TLDR : il 0x00 iniziale è un SIGN BY che aggiunge openssl solo per la stampa. NON è codificato nel certificato stesso. E suppongo che tu possa tagliare il byte principale (uno di 0x02, 0x03 o 0x04 ) del pubkey perché memorizza solo informazioni sulla codifica compressa o non compressa.

Chiave di esempio con nullbyte iniziale

Ecco un esempio di una chiave casuale che ho generato:

$ cat leading-nullbyte.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIN/37NFyCvL7brp4zljP83sNj1PvtFsp8dMR86EDwLZUoAoGCCqGSM49
AwEHoUQDQgAEK0acP7Ml6fgKy35YE7JGVP7AmNy7oJ6gl4QIqiwiSExbr4iDPfxT
81550HxXoiQiBJXBJxhgXYpIcJVmFGk20w==
-----END EC PRIVATE KEY-----

ec print leading-nullbyte.pem

Questa chiave è mostrata con il prefisso "00:" per la chiave privata.

Almeno quando usi la stampante graziosa openssl ...

$ openssl ec -noout -text -in leading-nullbyte.pem
read EC key
Private-Key: (256 bit)
priv:
    00:df:f7:ec:d1:72:0a:f2:fb:6e:ba:78:ce:58:cf:
    f3:7b:0d:8f:53:ef:b4:5b:29:f1:d3:11:f3:a1:03:
    c0:b6:54
pub:
    04:2b:46:9c:3f:b3:25:e9:f8:0a:cb:7e:58:13:b2:
    46:54:fe:c0:98:dc:bb:a0:9e:a0:97:84:08:aa:2c:
    22:48:4c:5b:af:88:83:3d:fc:53:f3:5e:79:d0:7c:
    57:a2:24:22:04:95:c1:27:18:60:5d:8a:48:70:95:
    66:14:69:36:d3
ASN1 OID: prime256v1
NIST CURVE: P-256

asn1parse leading-nullbyte.pem

... tuttavia, quando guardi realmente dentro la codifica ASN1 non c'è nessun prefisso 00: . Inizia subito con df: . E anche: la lunghezza è data come 32 ( l= 32 ). Non 33.

    5:d=1  hl=2 l=  32 prim:  OCTET STRING
      0000 - df f7 ec d1 72 0a f2 fb-6e ba 78 ce 58 cf f3 7b   ....r...n.x.X..{

Ecco le righe nel loro contesto:

$ openssl asn1parse -i -dump -in leading-nullbyte.pem
    0:d=0  hl=2 l= 119 cons: SEQUENCE
    2:d=1  hl=2 l=   1 prim:  INTEGER           :01
    5:d=1  hl=2 l=  32 prim:  OCTET STRING
      0000 - df f7 ec d1 72 0a f2 fb-6e ba 78 ce 58 cf f3 7b   ....r...n.x.X..{
      0010 - 0d 8f 53 ef b4 5b 29 f1-d3 11 f3 a1 03 c0 b6 54   ..S..[)........T
   39:d=1  hl=2 l=  10 cons:  cont [ 0 ]
   41:d=2  hl=2 l=   8 prim:   OBJECT            :prime256v1
   51:d=1  hl=2 l=  68 cons:  cont [ 1 ]
   53:d=2  hl=2 l=  66 prim:   BIT STRING
      0000 - 00 04 2b 46 9c 3f b3 25-e9 f8 0a cb 7e 58 13 b2   ..+F.?.%....~X..
      0010 - 46 54 fe c0 98 dc bb a0-9e a0 97 84 08 aa 2c 22   FT............,"
      0020 - 48 4c 5b af 88 83 3d fc-53 f3 5e 79 d0 7c 57 a2   HL[...=.S.^y.|W.
      0030 - 24 22 04 95 c1 27 18 60-5d 8a 48 70 95 66 14 69   $"...'.'].Hp.f.i
      0040 - 36 d3                                             6.

Quindi il 0x00 iniziale non è effettivamente codificato nel file del certificato. Mentre non ho dato un'occhiata al codice sorgente di openssl per quanto riguarda il fatto che sono propenso a chiamare questo bug di stampa.

Secondo RFC5915 (penso) una chiave EC è un intero UNSIGNED.

Chiave di esempio SENZA nullbyte iniziale

Ecco un'altra chiave casuale che ho generato. NON ha il prefisso 0x00 quando si usa la stampante openssl ec pretty.

Quindi questo mi dice che quel prefisso 0x00 non è necessariamente lì per ogni privkey EC.

$ cat no-leading-nullbyte.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAGcFoPfqfFZ5TDv71ZBBCctapiVKwZikE8HfKf61V1DoAoGCCqGSM49
AwEHoUQDQgAENPjKv9vobJnz1FSlSu5cNPyPwCvcsMmIr5HH92C+mZdVtanHwlTm
29IwOE5lSE8KMywIJs8pLCvX79kJhZ/upg==
-----END EC PRIVATE KEY-----

ec stampa no-leading-nullbyte.pem

$ openssl ec -noout -text -in no-leading-nullbyte.pem
read EC key
Private-Key: (256 bit)
priv:
    01:9c:16:83:df:a9:f1:59:e5:30:ef:ef:56:41:04:
    27:2d:6a:98:95:2b:06:62:90:4f:07:7c:a7:fa:d5:
    5d:43
pub:
    04:34:f8:ca:bf:db:e8:6c:99:f3:d4:54:a5:4a:ee:
    5c:34:fc:8f:c0:2b:dc:b0:c9:88:af:91:c7:f7:60:
    be:99:97:55:b5:a9:c7:c2:54:e6:db:d2:30:38:4e:
    65:48:4f:0a:33:2c:08:26:cf:29:2c:2b:d7:ef:d9:
    09:85:9f:ee:a6
ASN1 OID: prime256v1
NIST CURVE: P-256

asn1punto no-leading-nullbyte.pem

Qui di nuovo la lunghezza è data come 32:

    5:d=1  hl=2 l=  32 prim:  OCTET STRING
      0000 - 01 9c 16 83 df a9 f1 59-e5 30 ef ef 56 41 04 27   .......Y.0..VA.'

Analisi completa:

$ openssl asn1parse -i -dump -in no-leading-nullbyte.pem
    0:d=0  hl=2 l= 119 cons: SEQUENCE
    2:d=1  hl=2 l=   1 prim:  INTEGER           :01
    5:d=1  hl=2 l=  32 prim:  OCTET STRING
      0000 - 01 9c 16 83 df a9 f1 59-e5 30 ef ef 56 41 04 27   .......Y.0..VA.'
      0010 - 2d 6a 98 95 2b 06 62 90-4f 07 7c a7 fa d5 5d 43   -j..+.b.O.|...]C
   39:d=1  hl=2 l=  10 cons:  cont [ 0 ]
   41:d=2  hl=2 l=   8 prim:   OBJECT            :prime256v1
   51:d=1  hl=2 l=  68 cons:  cont [ 1 ]
   53:d=2  hl=2 l=  66 prim:   BIT STRING
      0000 - 00 04 34 f8 ca bf db e8-6c 99 f3 d4 54 a5 4a ee   ..4.....l...T.J.
      0010 - 5c 34 fc 8f c0 2b dc b0-c9 88 af 91 c7 f7 60 be   ...+........'.
      0020 - 99 97 55 b5 a9 c7 c2 54-e6 db d2 30 38 4e 65 48   ..U....T...08NeH
      0030 - 4f 0a 33 2c 08 26 cf 29-2c 2b d7 ef d9 09 85 9f   O.3,.&.),+......
      0040 - ee a6                                             ..

Extra: come faccio a sapere che 0x00 è un byte di segno?

... per sperimentazione:

Ho generato migliaia di chiavi in questo modo:

$ for i in $(seq -w 1000); do echo $i; openssl ecparam -name prime256v1 -genkey -noout > key.$i.pem; done

E poi li ho ordinati e contati per primo byte in questo modo:

$ for i in $(seq -w 1000); do openssl ec -noout -text -in key.$i.pem 2>/dev/null | grep '^priv:' -A1 | tail -1; done | sed 's/ *//' | sed 's/\(..\).*//' | sort | uniq -c

    496 00
      3 01
      3 02
      4 03
      5 04
      4 05
      5 06
      3 07
      1 08
      3 09
      1 0a
      3 0b
      2 0c
      2 0d
      3 0e
      4 0f
      4 11
      6 12
      1 14
      7 15
      3 16
      7 17
      4 18
      1 19
      6 1a
      3 1b
      3 1c
      3 1d
     11 1e
      3 1f
      6 20
      4 21
      2 22
      3 23
      8 24
      3 25
      2 26
      7 27
      3 28
      7 29
      4 2a
      4 2b
      9 2c
      2 2d
      5 2e
      2 2f
      5 30
      7 31
      6 32
      3 33
      6 34
      8 35
      5 36
      2 37
      2 38
      5 39
      2 3a
      1 3b
      4 3c
      3 3d
      2 3e
      2 3f
      2 40
      3 41
      5 42
      5 43
      3 44
      4 45
      5 46
      4 47
      5 48
      5 49
      5 4a
      5 4b
      8 4c
      6 4d
      3 4e
      5 4f
      4 50
      2 51
      4 52
      2 53
      2 54
      3 55
      7 56
      2 57
      5 58
      3 59
      3 5a
      5 5b
      2 5d
      1 5e
      9 5f
      3 60
      3 61
      3 62
      6 63
      3 64
      1 65
      7 66
      4 67
      3 68
      4 69
      4 6a
      3 6b
      6 6c
      4 6d
      3 6e
      3 6f
      7 70
      4 71
      2 72
      5 73
      2 74
      1 75
      5 76
      3 77
     10 78
      2 79
      7 7a
      5 7b
      6 7c
      6 7d
      5 7e
      5 7f

Il byte più alto è 0x7f. E questo è il byte finale che ha ancora un 0 come il bit più significativo. (Non posterò tutti i migliaia di questi qui, ma tutti i privkey che avevano 0x00 come primo byte avevano il loro secondo byte > = 0x80. (Non c'erano i privati che iniziarono con 0x0000.) E tutti i privkey non avevano 0x00 come il loro primo byte aveva il loro secondo byte < = 0x7f.)

    
risposta data 27.06.2017 - 22:58
fonte

Leggi altre domande sui tag