On iOS, the Certificate, Key, and Trust Services API contains the following padding types:
kSecPaddingNone
kSecPaddingPKCS1
kSecPaddingPKCS1MD2
kSecPaddingPKCS1MD5
kSecPaddingPKCS1SHA1
A user on the Apple CDSA mailing list says that "kSecPaddingPKCS1 [...] is the same as PKCS #1 1.5". The Certificate, Key, and Trust Services Reference annotates the latter three padding types (kSecPaddingPKCS1MD2
, kSecPaddingPKCS1MD5
, and kSecPaddingPKCS1SAH
) with "Standard ASN.1 padding will be done, as well as PKCS1 padding of the underlying RSA operation".
kSecPaddingPKCS1
? kSecPaddingPKCS1
just the raw padding of the underlying RSA operation according to RFC 3447?SecKeyRawSign()
, does a developer need to use kSecPaddingPKCS1
and perform the ASN.1 padding herself? Is the ASN.1 padding necessary or can it be omitted?Any hint that points me in the right direction is highly appreciated.
PKCS#1 contains two "paddings" for signatures with RSA, the "new" one (called PSS, added in version 2.1) and the "old" one (renamed "v1.5" since it was already in version 1.5 of PKCS#1). We are talking about the v1.5 padding.
When some data is signed, it is first hashed with a suitable hash function (e.g. SHA-1), then the hash value (20 bytes if using SHA-1) is wrapped into two successive layers:
The hash value is encoded into an ASN.1-based structure which also specifies which hash function was used. In practice, if the hash value is H, then the first wrapping results in the sequence of bytes A || H where "||" is concatenation, and "A" is a header which is specific to the hash function (typically 15 to 20 bytes).
The "A || H" is expanded with some extra bytes:
0x00 0x01 0xFF 0xFF ... 0xFF 0x00 || A || H
The number of bytes of value 0xFF is adjusted to that the total size equals the size of the RSA modulus (i.e. 128 bytes for a 1024-bit RSA key).
The second step is what PKCS#1 calls "type 1 padding".
kSecPaddingPKCS1
means that the function performs only the second step: it assumes that the input data is already the proper "A || H". Note that SSL/TLS (up to version 1.1) uses a signature variant which requires this mode (there's no "A", but there are two hash functions). With kSecPaddingPKCS1SHA1
, the signature function expects the hash value as input, and adds the "A" header itself.
For a proper, standards-compliant signature which can be verified by third-party implementations, the "A" header must be added at some point. You can add it yourself and use kSecPaddingPKCS1
, or use kSecpaddingPKCS1SHA1
and let the engine add it itself, which is probably less error-prone.
(As of 2011, use of SHA-1 is not recommended; you'd better switch to SHA-256 or SHA-512. Also, the API you are trying to use seem to be quite low-level, and the whole thing suspiciously looks as if you are tying to implement your own cryptographic protocol instead of using an existing library or framework.)