On 2010-10-16 06:25 PDT, Matej Kurpel wrote: > Hello, > I am developing a PKCS#11 module to be used with Thunderbird. However, I > have trouble providing a valid signature for e-mails. The mechanism used > is CKM_RSA_PKCS and I have a 1024bit private key along with the > certificate, stored on the token. The signature is generated in a C# > .NET CF program running on the device, using this piece of code: > > RSACryptoServiceProvider rsa = > PKCS11Library.TryLoadPK(Encoding.ASCII.GetString(keyPath, 0, > keyPath.Length), out keyRawData); // this returns a valid > RSACryptoServiceProvider instance > signature = rsa.SignData(data, new SHA1CryptoServiceProvider()); //signs > the data we need > > I am not sure about the second parameter of the rsa.SignData method - > the documentation says it is of type "object" and it's the mechanism to > be used to sign the data. I cannot think of any more appropriate object > to be passed there than SHA1CryptoServiceProvider.
This isn't really the place to come for advice about C# crypto ... but ... the SignData method provides the wrong level of functionality for CKM_RSA_PKCS. The entire RSA signature creation process usually includes these steps: 1) Choose a hash algorithm (e.g. SHA-something or MD5), get the OID string (number) value that identifies that algorithm, and use that algorithm to hash all the data to be signed. 2) Construct an ASN.1 DER formatted buffer called a "DigestInfo" using that OID string and that hash value. 3) Construct a PKCS#1 formatted buffer (either v 1.5 or v2.0) from that DER formatted buffer. 4) Perform an RSA private key operation on that PKCS#1 formatted buffer. In some applications, steps 2 and/or 3 are modified, and custom buffer formats are used instead of the pure DigestInfo and/or PKCS#1 formats. The CKM_RSA_PKCS mechanism you're attempting to implement does only the last two of those steps. It treats the input it is given as a DigestInfo. It then does the PKCS#1 formatting according to PKCS#1 version 1.5. This gives its user the flexibility to implement the normal DigestInfo buffer format, or any other custom format. PKCS#1 Version 2.0 formatting is incompatible with CKM_RSA_PKCS. PKCS#1 Version 2.0 formatting is done by another PKCS#11 mechanism, namely CKM_RSA_PKCS_OAEP. The SignData method you're trying to use does all the above steps. It wants the input to step 1. Since you're implementing CKM_RSA_PKCS, the data you're given is the input to step 3, the output from step 2. You can deconstruct it and obtain from it the output from step 1, but you cannot go back to having the input to step 1, because the hash is irreversible. So, I think you cannot use SignData to implement CKM_RSA_PKCS. C#'s RSACryptoServiceProvider class also features a SignHash method that does the last three of those steps. It expects to receive, as input, the hash value and the OID string. It constructs the DigestInfo and the PKCS#1 buffer and does the RSA private key operation. Whether it formats the PKCS#1 buffer according PKCS#1 version 1.5 or version 2.0 is unknown to me. I couldn't find any reference to PKCS in MSDN's C# documentation. -- dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto