RSA key length 140 Byte instead of 128 Byte

I'm using SecKey in an iOS project to generate a new RSA key pair. The defined keySize is 1024 Bit, which means I should get back a 128 Byte key.

But when I'm using the methods SecKey.CreateRandomKey or SecKey.GenerateKeyPair I always get a 140 byte long key back. Since I have to send the public key in my app to an otrher system, I need a 128 Byte key (+ 4 Byte paddingg data).


How can I get the required key?

The defined keySize is 1024 Bit, which means I should get back a 128 Byte key.

This is not how RSA keys work. RSA keys are stored as an ASN.1 structure, meaning that the length of the raw key bytes is only indirectly related to the key length in bits.

You can learn more about this formatting in RFC 3447 (aka PKCS#1). Specifically, look at Sections 3.1 and 3.2, which define the basics, and Appendices A.1.1 and A.1.2 which defines the

RSAPublicKey
and
RSAPrivateKey
ASN.1 structures.

I need a 128 Byte key (+ 4 Byte paddingg data).

I’ve not seen this RSA public key format before. Do you know what standard defines it?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello Eskimo, thank you for your answer.

The only description I have is the following ("symmetric key" means an RSA encrypted value that needs to be exchanged and compared between the systems):


The Key exchange shall be based on asymmetric RSA 1024Bit Key with CBC.

The Application shall generate two 128 Byte Keys for secure transmission of the symmetric key.

- Public key to be transmitted to the access point

- Private Key for decrypting the encrypted symmetric key


Since I have no experience with RSA encryption, I had to ask the developers of the system for the standard used, which requires the 128-bit key for it. But I haven't received an answer yet. As soon as they answer, I hope I can tell you more.

I can fill in some of the details here, but not enough to let you get things running. You’ll still need to follow up with the folks who designed whatever protocol you’re implementing.

RSA encryption works on blocks of data, where the size of the block is determined by the key size. So an 1024 bit RSA key will always encrypt and decrypt 128 byte blocks.

The contents of these blocks varies by protocol. Most protocols don’t use RSA directly but rather generate a random symmetric key and then encrypt that symmetric key using RSA. As this symmetric key is not 128 bytes long, it must be padded to fit up to the RSA block size. It’s critical that you do this padding correctly to avoid security vulnerabilities. Most folks using one of a few standard padding algorithm, for example, OAEP.

In your case it seems like that the protocol designers are using AES in CBC mode and then encrypting a randomly generated AES key using RSA. However, there’s still a bunch of missing information, for example:

  • Is it AES-128 or AES-256?

  • How is the initialisation vector (IV) handled?

  • How the AES key is padding for RSA encryption?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I have now received further information. I am expected to transmit only the modulus value (which should have 128 bytes) and the exponent (4 bytes) in a "combined" byte array - not the public key as such but only the components of the key and not as a structure.

In addition, it is "defined" that the exponent should always consist of the bytes "00 01 00 01" (= 4 bytes) - don't know why and how I can achieve this.

If this is actually safe and whether it corresponds to the RSA standard for the exchange of the public key I cannot judge.


For me the question now arises how I can get the modulus and the exponent values as a byte array using SecKey and having the public key.

Maybe you can help me at this point? Also as references to documentation where the procedure is explained.

how I can get the modulus and the exponent values as a byte array using

SecKey
and having the public key.

iOS has no API for this. My recommendation is that you change your server to support a more sensible way of transporting RSA keys. This approach makes things unnecessarily difficult for iOS clients.

And while you’re doing that you can upgrade the security (-:

If this is actually safe …

Personally, I don’t consider anything that uses 1024-bit RSA keys to be safe. You can find links to the ongoing debate about the safety of small RSA keys in the fount of all knowledge.

Anyway, if you absolutely have to do this then you’ll need to write (or acquire) ASN.1 parsing code. Specifically, the value you get back from

SecKeyCopyExternalRepresentation
is a DER-encoded ASN.1
RSAPublicKey
structure (per RFC 3447). For debugging purposes you can look into this structure using dumpasn1. For example:
$ dumpasn1 public.asn1 
   0  159: SEQUENCE {
   3   13:   SEQUENCE {
   5    9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
  16    0:     NULL
         :     }
  18  141:   BIT STRING, encapsulates {
  22  137:     SEQUENCE {
  25  129:       INTEGER
         :         00 C1 BE 8F CB 91 9A 02 34 A2 4F 5B 27 3E 7D F1
         :         34 24 5A 65 7B 41 50 8B D0 1E A1 9B DB FF D0 F6
         :         00 82 08 CD 46 47 8B 82 F9 4A D9 16 EE B1 9C 15
         :         12 A6 00 02 33 48 05 F3 70 92 8B 70 B2 C3 BE 2B
         :         B0 C4 8F 85 80 83 B4 A9 DB 1F A4 ED CD E0 2D 0E
         :         DE 08 49 33 37 92 05 55 FB 25 3B B9 BD 55 11 C6
         :         AE B8 F3 86 C9 18 06 A3 72 20 5B 38 C0 C9 80 EA
         :         23 45 55 B1 EA CA 8A 8C 96 54 22 1E 75 1E EE DF
         :                 [ Another 1 bytes skipped ]
 157    3:       INTEGER 65537
         :       }
         :     }
         :   }

0 warnings, 0 errors.

The first

INTEGER
element is the
modulus
field; the second is the
publicExponent
field. The value of the latter is 65537, or 0x00010001, which aligns with your “00 01 00 01” requirement.

IMPORTANT The

modulus
field in this example is 129 bytes, not 128 bytes, because of a leading zero. This leading zero shows up due to the way DER encodes ASN.1
INTEGER
elements. Dealing with this either requires you to understand DER, so you can write your own parser, or use some sort of DER parsing library. If you decide to attempt the former you can find a whole bunch of useful info hanging off the ASN.1 Wikipedia page.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you very much. That helped me a lot.


Unfortunately I have to do it this way, I have no choice.

And I have to write the parser myself, because I'm not allowed to use Third-party components.


But that's okay, it will take a little longer until I'm done with it 🙂

Thanks also for the links, which help me with that.

RSA key length 140 Byte instead of 128 Byte
 
 
Q