88https://github.com/aosp-mirror/platform_system_core/blob/c55fab4a59cfa461857c6a61d8a0f1ae4591900c/libcrypto_utils/android_pubkey.c
99
1010typedef struct RSAPublicKey {
11- // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE.
11+ // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE_WORDS
1212 uint32_t modulus_size_words;
1313
1414 // Precomputed montgomery parameter: -1 / n[0] mod 2^32
1515 uint32_t n0inv;
1616
17- // RSA modulus as a little-endian array.
17+ // RSA modulus as a little-endian array
1818 uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE];
1919
20- // Montgomery parameter R^2 as a little-endian array of little-endian words.
20+ // Montgomery parameter R^2 as a little-endian array of little-endian words
2121 uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE];
2222
2323 // RSA modulus: 3 or 65537
2828from __future__ import print_function
2929
3030import os
31- import six
3231import base64
3332import socket
3433import struct
4039# Size of an RSA modulus such as an encrypted block or a signature.
4140ANDROID_PUBKEY_MODULUS_SIZE = (2048 // 8 )
4241
43- # Size of an encoded RSA key.
44- ANDROID_PUBKEY_ENCODED_SIZE = \
45- (3 * 4 + 2 * ANDROID_PUBKEY_MODULUS_SIZE )
46- # (3 * sizeof(uint32_t) + 2 * ANDROID_PUBKEY_MODULUS_SIZE)
42+ # Python representation of "struct RSAPublicKey":
43+ ANDROID_RSAPUBLICKEY_STRUCT = (
44+ '<' # Little-endian
45+ 'L' # uint32_t modulus_size_words;
46+ 'L' # uint32_t n0inv;
47+ '{modulus_size}s' # uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE];
48+ '{modulus_size}s' # uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE];
49+ 'L' # uint32_t exponent;
50+ ).format (modulus_size = ANDROID_PUBKEY_MODULUS_SIZE )
51+
4752
4853# Size of the RSA modulus in words.
4954ANDROID_PUBKEY_MODULUS_SIZE_WORDS = (ANDROID_PUBKEY_MODULUS_SIZE // 4 )
5257def _to_bytes (n , length , endianess = 'big' ):
5358 """partial python2 compatibility with int.to_bytes
5459 https://stackoverflow.com/a/20793663"""
55- if six . PY2 :
60+ if not hasattr ( n , 'to_bytes' ) :
5661 h = '{:x}' .format (n )
5762 s = ('0' * (len (h ) % 2 ) + h ).zfill (length * 2 ).decode ('hex' )
5863 return s if endianess == 'big' else s [::- 1 ]
@@ -62,16 +67,11 @@ def _to_bytes(n, length, endianess='big'):
6267def decode_pubkey (public_key ):
6368 """decodes a public RSA key stored in Android's custom binary format"""
6469 binary_key_data = base64 .b64decode (public_key )
65- key_struct = struct .unpack (('<LL' +
66- 'B' * ANDROID_PUBKEY_MODULUS_SIZE +
67- 'B' * ANDROID_PUBKEY_MODULUS_SIZE +
68- 'L' ), binary_key_data )
69- modulus_size_words = key_struct [0 ]
70- n0inv = key_struct [1 ]
71- modulus = reversed (key_struct [2 : 2 + ANDROID_PUBKEY_MODULUS_SIZE ])
72- rr = reversed (key_struct [2 + ANDROID_PUBKEY_MODULUS_SIZE :
73- 2 + 2 * ANDROID_PUBKEY_MODULUS_SIZE ])
74- exponent = key_struct [- 1 ]
70+ modulus_size_words , n0inv , modulus_bytes , rr_bytes , exponent = \
71+ struct .unpack (ANDROID_RSAPUBLICKEY_STRUCT , binary_key_data )
72+ assert modulus_size_words == ANDROID_PUBKEY_MODULUS_SIZE_WORDS
73+ modulus = reversed (modulus_bytes )
74+ rr = reversed (rr_bytes )
7575 print ('modulus_size_words:' , hex (modulus_size_words ))
7676 print ('n0inv:' , hex (n0inv ))
7777 print ('modulus: ' , end = '' )
@@ -83,15 +83,13 @@ def decode_pubkey(public_key):
8383
8484def decode_pubkey_file (public_key_path ):
8585 with open (public_key_path , 'rb' ) as fd :
86- decode_pubkey (fd .read ())
86+ decode_pubkey (fd .read ())
8787
8888
8989def encode_pubkey (private_key_path ):
9090 """encodes a public RSA key into Android's custom binary format"""
9191 key = Crypto .PublicKey .RSA .import_key (private_key_path )
9292
93- # Store the modulus size.
94- key_buffer = struct .pack ('<L' , ANDROID_PUBKEY_MODULUS_SIZE_WORDS )
9593 # Compute and store n0inv = -1 / N[0] mod 2^32.
9694 # BN_set_bit(r32, 32)
9795 r32 = 1 << 32
@@ -101,19 +99,21 @@ def encode_pubkey(private_key_path):
10199 n0inv = Crypto .Util .number .inverse (n0inv , r32 )
102100 # BN_sub(n0inv, r32, n0inv)
103101 n0inv = r32 - n0inv
104- key_buffer += struct .pack ('<L' , n0inv )
105102
106- # Store the modulus.
107- key_buffer += _to_bytes (key .n , ANDROID_PUBKEY_MODULUS_SIZE , 'little' )
108103 # Compute and store rr = (2^(rsa_size)) ^ 2 mod N.
109104 # BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8)
110105 rr = 1 << (ANDROID_PUBKEY_MODULUS_SIZE * 8 )
111106 # BN_mod_sqr(rr, rr, key->n, ctx)
112107 rr = (rr ** 2 ) % key .n
113- key_buffer += _to_bytes (rr , ANDROID_PUBKEY_MODULUS_SIZE , 'little' )
114108
115- key_buffer += struct .pack ('<L' , key .e )
116- return key_buffer
109+ return struct .pack (
110+ ANDROID_RSAPUBLICKEY_STRUCT ,
111+ ANDROID_PUBKEY_MODULUS_SIZE_WORDS ,
112+ n0inv ,
113+ _to_bytes (key .n , ANDROID_PUBKEY_MODULUS_SIZE , 'little' ),
114+ _to_bytes (rr , ANDROID_PUBKEY_MODULUS_SIZE , 'little' ),
115+ key .e
116+ )
117117
118118
119119def get_user_info ():
@@ -135,7 +135,7 @@ def write_public_keyfile(private_key_path, public_key_path):
135135 private_key = private_key_file .read ()
136136
137137 public_key = encode_pubkey (private_key )
138- assert len (public_key ) == ANDROID_PUBKEY_ENCODED_SIZE
138+ assert len (public_key ) == struct . calcsize ( ANDROID_RSAPUBLICKEY_STRUCT )
139139 with open (public_key_path , 'wb' ) as public_key_file :
140140 public_key_file .write (base64 .b64encode (public_key ))
141141 public_key_file .write (get_user_info ().encode ())
0 commit comments