3.1.1.3 Client Public Keys Object Format

A client MUST generate encryption and signature key pairs for the client device and each account on the device. The signature key pairs MUST be generated using the RSA public key algorithm [PKCS1], and the encryption key pair MUST be generated using either the ElGamal public key algorithm [CRYPTO] with Crypto++ padding or the RSA public key algorithm [PKCS1].<3>

Crypto++ ElGamal encryption is done as follows:

  1. Inputs:

    • LenM: Number of bytes in the modulus of the underlying Diffie-Hellman group.

    • LenP: Number of bytes of the plaintext, which is the input for encryption.

  2. Allocate a block of (LenM minus 1) bytes.

  3. Generate (LenM minus 2 minus LenP) bytes of randomness, and copy them starting at offset 0 of the allocated block.

  4. Copy the plaintext after the (LenM minus 2 minus LenP) random bytes in the allocated block. This will occupy almost all the remaining space in the block, except for the last byte.

  5. Set the last byte of the allocated block at offset (LenM minus 2) to LenP.

  6. Apply ElGamal encryption to the resulting block, interpreting the block as if it was in Big Endian format. The result of encryption is encoded into Big Endian format as well.

Crypto++ ElGamal decryption is done as follows:

  1. Treat the encrypted input as Big Endian format, and apply ElGamal decryption to get the decrypted block, which also will be in Big Endian format.

  2. Get the first byte of the decrypted block, which is LenP because it is in Big Endian format and therefore the order of bytes is reversed.

  3. Get the next LenP bytes of the decrypted block, which is the original plaintext in Big Endian format.

  4. Convert the original plaintext from Big Endian to Little Endian.

When registering a device or an account, the client MUST send the server a public keys object that contains information about the public halves of the encryption and signature key pairs that the client has generated for the device or account. A public keys object MUST be formatted as follows, with fields as specified in the following table.


0


1


2


3


4


5


6


7


8


9

1
0


1


2


3


4


5


6


7


8


9

2
0


1


2


3


4


5


6


7


8


9

3
0


1

Signature Algorithm Name (variable)

...

Encryption Algorithm Name (variable)

...

Signature Key Algorithm Name (variable)

...

Encryption Key Algorithm Name (variable)

...

Signature Public Key Length

Signature Public Key (variable)

...

Encryption Public Key Length

Encryption Public Key (variable)

...

Signature Algorithm Name (variable): Null-terminated ANSI string that MUST be set to "RSA". This field specifies the name of the signature algorithm.

Encryption Algorithm Name (variable): Null-terminated ANSI string that MUST be set to "ELGAMAL" or "RSA". This field specifies the name of the encryption algorithm.

Signature Key Algorithm Name (variable): Null-terminated ANSI string that MUST be set to "RSA". This field specifies the name of the type of signature key used in the signature algorithm.

Encryption Key Algorithm Name (variable): Null-terminated ANSI string that MUST be set to "DH" or "RSA". This field specifies the name of the type of encryption key used in the encryption algorithm.

Signature Public Key Length (4 bytes): Length of the Signature Public Key field.

Signature Public Key (variable): DER-encoded signature public key.

Encryption Public Key Length (4 bytes): Length of the Encryption Public Key field.

Encryption Public Key (variable): DER-encoded encryption public key.