Re: PKCS#11: C_Sign provides invalid signature
On 2010-10-16 11:39 PDT, Matej Kurpel wrote: > On 16. 10. 2010 18:33, Nelson B Bolyard wrote: >> 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, [...] > Thank you, Nelson, it works now. I used the SignHash method instead, > with the OID string "1.3.14.3.2.26", which means SHA1. And I took just > the last 20 bytes of the provided data to sign - which is the hash. You should not assume that the DigestInfo you're given will always contain a SHA1 hash. It may contain other hashes from other algorithms, of other lengths. It will always contain the proper OID string for the hash it has used. So, you should parse the DigestInfo you're given as input. Take it apart. Pull out the OID string and the hash string using the explicit lengths encoded in the DigestInfo, then pass those to SignHash. Parsing the DigestInfo is very straightforward. I'm sure you can figure it out. -- /Nelson Bolyard -- dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto
Re: PKCS#11: C_Sign provides invalid signature
On 16. 10. 2010 18:33, Nelson B Bolyard wrote: 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. Thank you, Nelson, it works now. I used the SignHash method instead, with the OID string "1.3.14.3.2.26", which means SHA1. And I took just the last 20 bytes of the provided data to sign - which is the hash. M. Kurpel -- dev-tech-crypto mailing list dev-tech-crypto@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-crypto
Re: PKCS#11: C_Sign provides invalid signature
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
PKCS#11: C_Sign provides invalid signature
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. Now, the problem is that the signed e-mail is sent correctly but after receiving it, Thunderbird states that the signature is invalid. My question is, is there any format NSS (Thunderbird) needs the signature in? Does the signature I am providing, look properly at a first glance? (Please look at line 45 in the pkcs11-spy log I am attaching). PKCS11 SPY LOG BEGIN 32: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x1 [in] pTemplate[2]: CKA_IDrequested with 0 buffer CKA_CLASS requested with 0 buffer [out] pTemplate[2]: CKA_IDhas size 4 CKA_CLASS has size 4 Returned: 0 CKR_OK 33: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x1 [in] pTemplate[2]: CKA_IDrequested with 4 buffer CKA_CLASS requested with 4 buffer [out] pTemplate[2]: CKA_ID[size : 0x4 (4)] 0100 CKA_CLASS CKO_CERTIFICATE Returned: 0 CKR_OK 34: C_FindObjectsInit [in] hSession = 0x1 [in] pTemplate[2]: CKA_ID[size : 0x4 (4)] 0100 CKA_CLASS CKO_PRIVATE_KEY Returned: 0 CKR_OK 35: C_FindObjects [in] hSession = 0x1 [in] ulMaxObjectCount = 0x1 [out] ulObjectCount = 0x1 Object 2 Matches Returned: 0 CKR_OK 36: C_FindObjectsFinal [in] hSession = 0x1 Returned: 0 CKR_OK 37: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_KEY_TYPE requested with 4 buffer [out] pTemplate[1]: CKA_KEY_TYPE CKK_RSA Returned: 0 CKR_OK 38: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_TOKEN requested with 1 buffer [out] pTemplate[1]: CKA_TOKEN True Returned: 0 CKR_OK 39: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_PRIVATE requested with 1 buffer [out] pTemplate[1]: CKA_PRIVATE True Returned: 0 CKR_OK 40: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_MODULUS requested with 0 buffer [out] pTemplate[1]: CKA_MODULUS has size 128 Returned: 0 CKR_OK 41: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_MODULUS requested with 128 buffer [out] pTemplate[1]: CKA_MODULUS [size : 0x80 (128)] D0B54A0E 53C59293 278EE27A 928C30CB 4A1942F6 DE32B8A4 951196DF 53FE8469 7225D5B0 98421497 C7C70428 2468A022 C17B0E51 E17B86C4 E0624BED 398FCDCD 422F789A 9518E4D4 DC07DA20 186BD121 2B80725E 8AE34A68 78FBC43E 6F3A2A95 DC808706 01C8A576 B5A072E1 2F773240 F60AF083 5021112A E9F0CB7F 98A7EEC5 Returned: 0 CKR_OK 42: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x2 [in] pTemplate[1]: CKA_PRIVATE requested with 1 buffer [out] pTemplate[1]: CKA_PRIVATE True Returned: 0 CKR_OK 43: C_OpenSession [in] slotID = 0x0 [in] flags = 0x4 pApplication=068DE800 Notify=5F8B5E19 [out] *phSession = 0x2 Returned: 0 CKR_OK 44: C_SignInit [in] hSession = 0x2 pMechanism->type=CKM_RSA_PKCS [in] hKey = 0x2 Returned: 0 CKR_OK 45: C_Sign [in] hSession = 0x2 [in] pData[ulDataLen] [size : 0x23 (35)] 30213009 06052B0E 03021A05 0004149A E91D78EE 1FDC8F4F A65E41A2 1263BF31 94C4D2 [out] pSignature[*pulSignatureLen] [size : 0x80 (128)] 63334030 9439D903 9645AC11 C1C05136 0B17A571 16E3F223 06CA4941 CB0721E5 194CF829 43DF0DE9 AB6BD5DF 051A8906 1D974171 6879468E 1F043C4B 7763E607 D0163299 54AA23B4 4BD221B7 B8F1F880 23D7E032 2AB6C7D9 18C29AEF 23603C08 E91BE397 303271E4 1850AC57 B53CD457 D10056DE 3C7CCB0F 99AFFF51 86CC3E28 Returned: 0 CKR_OK 46: C_CloseSession [in] hSession = 0x2 Returned: 0 CKR_OK 47: C_GetAttributeValue [in] hSession = 0x1 [in] hObject = 0x1 [in] pTemplate[2]: CKA_IDrequested with 0 buffer CKA_CLASS requested with 0 buffer [out] pTemplate[2]: CKA_IDhas size 4 CKA_CLASS