Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CryptoAPI vs. CAPICOM

178 views
Skip to first unread message

news.microsof.com

unread,
Aug 31, 2004, 5:37:26 AM8/31/04
to
Hi,

Im signing a mail with a digital signature, using CAPICOM to get my
certificate and sign my data, that works fine.

My problem is that when I sign my data for the mail:

szSignature = oSignedData.Sign(oSigner, True, CAPICOM_ENCODE_BINARY)

the thirt party (TDC, CA in denmark) comes up with a prompt box to type in
password for the certificate. That is a problem because my code has to be
running on a server.

TDC says that I have to use the command from the CryptoAPI:
CryptSetKeyParam(hash,Password,)
to set the password so it is not asking for it.

Then I can sign my data without it prompt me for a password.

So my question is:

How do I sign my mail using CryptoAPI when I can not use CAPICOM ?

or is there a way to sign data with password from CAPICOM ?

Best Regards

Kim

Private Function SignMessage(ByRef oMsg As CDO.Message, bClear As Boolean)
As Boolean
Dim oSignedMsg As New CDO.Message
Dim oBodyPart As CDO.IBodyPart
Dim cFields As ADODB.Fields
Dim oStream As ADODB.Stream
Dim oSignedData As New CAPICOM.SignedData
Dim oUtilities As New CAPICOM.Utilities
Dim oAttribute As New CAPICOM.Attribute
Dim oSignerCertificate As CAPICOM.Certificate
Dim cSignerCertificates As CAPICOM.Certificates
Dim oStore As New CAPICOM.Store
'Dim szSignature, byteSignature() As Byte

On Error GoTo ErrorHandler

' create the SignedData object we will use to create the PKCS7
Set oSignedData = New CAPICOM.SignedData

' create the new message
Set oSignedMsg = New CDO.Message

' select the signer certificate
oStore.Open CAPICOM_CURRENT_USER_STORE, "My",
CAPICOM_STORE_OPEN_READ_ONLY
Set cSignerCertificates =
oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY,
CERT_KEY_SPEC_PROP_ID).Find(CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY,
"Secure Email")

Select Case cSignerCertificates.Count
Case 0
MsgBox ("Error: No signing certificate can be found.")
Case 1
oSigner.Certificate = cSignerCertificates(1)
Case Else
Set cSignerCertificates = cSignerCertificates.Select("S/MIME
Certificates", "Please select a certificate to sign with.")
If (cSignerCertificates.Count = 0) Then
MsgBox ("Error: Certificate selection dialog was
cancelled.")
Exit Function
End If
oSigner.Certificate = cSignerCertificates(1)
End Select

' set the from field based off of the selected certificate
oSignedMsg.From =
oSigner.Certificate.GetInfo(CAPICOM_CERT_INFO_SUBJECT_EMAIL_NAME)


' set the signing time in UTC time
Set oAttribute = New CAPICOM.Attribute
oAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME
oAttribute.Value = oUtilities.LocalTimeToUTCTime(Now)
oSigner.AuthenticatedAttributes.Add oAttribute

Select Case bClear
Case True
' this is to be a clear text signed message so we need to copy the
interesting
' parts (sender, recipient, and subject) into the new header
oSignedMsg.To = oMsg.To
oSignedMsg.CC = oMsg.CC
oSignedMsg.Subject = oMsg.Subject

Set oBodyPart = oSignedMsg.BodyPart.AddBodyPart
Set cFields = oBodyPart.Fields
cFields.Item(cdoContentType).Value =
oMsg.BodyPart.BodyParts(1).Fields.Item(cdoContentType).Value
cFields.Update

Set oStream = oBodyPart.GetDecodedContentStream
oStream.WriteText
oMsg.BodyPart.BodyParts(1).GetDecodedContentStream.ReadText
oStream.Flush

' set the content to be signed
oSignedData.Content =
StrConv(oSignedMsg.BodyPart.BodyParts(1).GetStream.ReadText, vbFromUnicode)

' sign the content
szSignature = oSignedData.Sign(oSigner, True, CAPICOM_ENCODE_BINARY)

' Get the string data as a byte array
byteSignature = szSignature

' Attach the signature and let CDO base64 encode it
Set oBodyPart = oSignedMsg.BodyPart.AddBodyPart
Set cFields = oBodyPart.Fields
oBodyPart.Fields.Item("urn:schemas:mailheader:content-type").Value =
"application/x-pkcs7-signature" & vbCrLf & "Name = ""smime.p7s"""

oBodyPart.Fields.Item("urn:schemas:mailheader:content-transfer-encoding").Va
lue = "base64"

oBodyPart.Fields.Item("urn:schemas:mailheader:content-disposition").Value =
"attachment;" & vbCrLf & "FileName=""smime.p7s"""
cFields.Update

Set oStream = oBodyPart.GetDecodedContentStream
oStream.Type = ADODB.StreamTypeEnum.adTypeBinary
oStream.Write (byteSignature)
oStream.Flush

' Set the messages content type, this needs to be done last to
ensure it is not changed when we add the BodyParts
oSignedMsg.Fields.Item("urn:schemas:mailheader:content-type").Value
= "multipart/signed;" & vbCrLf &
"protocol=""application/x-pkcs7-signature"";" & vbCrLf & "micalg=SHA1;"
oSignedMsg.Fields.Update

Case False
' this is to be a opaquely signed message so we need to copy the
entire message into our
' new encrypted message
oSignedMsg.DataSource.OpenObject oMsg, cdoIMessage

' Set up main bodypart
Set oBodyPart = oSignedMsg.BodyPart
oBodyPart.ContentMediaType = "application/pkcs7-mime;" & vbCrLf &
"smime-type=signed-data;" & vbCrLf & "name=""smime.p7m"""
oBodyPart.ContentTransferEncoding = "base64"
oBodyPart.Fields("urn:schemas:mailheader:content-disposition") =
"attachment;" & vbCrLf & "FileName=""smime.p7m"""
oBodyPart.Fields.Update

' set the from field based off of the selected certificate
oMsg.From =
oSigner.Certificate.GetInfo(CAPICOM_CERT_INFO_SUBJECT_EMAIL_NAME)

' set the content to be signed
oSignedData.Content = StrConv(oMsg.BodyPart.GetStream.ReadText,
vbFromUnicode)

' Sign the content
szSignature = oSignedData.Sign(oSigner, False,
CAPICOM_ENCODE_BINARY)

' Get the string data as a byte array
byteSignature = szSignature

' Attach the signature and let CDO base64 encode it
Set oStream = oBodyPart.GetDecodedContentStream
oStream.Type = ADODB.StreamTypeEnum.adTypeBinary
oStream.Write (byteSignature)
oStream.Flush
End Select


' Signing Was sucessfull
SignMessage = True
Set oMsg = oSignedMsg

GoTo CleanUp

ErrorHandler:
'If the user cancels, don't display error message
If Err.Number <> CAPICOM_E_CANCELLED Then
MsgBox "Error: " & Hex(Err.Number) & ": " & Err.Description
End If
Err.Clear

' An error occurred
SignMessage = False
Set oMsg = Nothing

CleanUp:
Set oSignedMsg = Nothing
Set oBodyPart = Nothing
Set cFields = Nothing
Set oStream = Nothing
Set oSignedData = Nothing
Set oUtilities = Nothing
Set oAttribute = Nothing
Set oSignerCertificate = Nothing
Set cSignerCertificates = Nothing
Set oStore = Nothing
End Function

Shawn Corey [MSFT]

unread,
Aug 31, 2004, 6:10:38 PM8/31/04
to
The problem is that the certificate was installed with a password required
for access to the private key and unfortunatly there is no current way for
CAPICOM to supply the password programatically, it will always prompt. Could
the certificate that is used for signing be changed to one that does not
have the private key protected with a password, or could the cert/key could
be exported and reimported without requiring a password?

--
Thanks,
Shawn

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


"news.microsof.com" <k...@microsoft.com> wrote in message
news:uClxn3zj...@TK2MSFTNGP15.phx.gbl...

wayne sun[MSFT]

unread,
Aug 31, 2004, 9:01:05 PM8/31/04
to
Or if you could load the certificate with private key from a .pfx file, you
can call Signer.Load(...), which you could provide the password.

Signer.Load
The Load method loads a signing certificate from a specified .pfx file.
Sub Load( _
ByVal FileName As String, _
[ ByVal Password As String ] _
)Parameters
FileName
Name of the .pfx file that contains the signing certificate.
Password
[optional] String containing the plaintext password used to open the file.
Up to 32 Unicode characters, including a NULL terminator, can be used for
the password. The default value is an empty string ("")

--

This posting is provided "AS IS" with no warranties, and confers no rights.

"Shawn Corey [MSFT]" <shaw...@online.microsoft.com> wrote in message
news:%23OwtCd6...@TK2MSFTNGP15.phx.gbl...

Kim Madsen

unread,
Sep 1, 2004, 9:06:41 AM9/1/04
to
Thanks for the answer, It has to have the password to match the Danish law
for signing mail with Digital Signature.

But perhaps it will work with loading it in as a file, but do you know how
to get my certificete from CSP store saved as a file with my private key ??

Best Regards

Kim


"wayne sun[MSFT]" <wayn...@online.microsoft.com> skrev i en meddelelse
news:ugoAd87j...@TK2MSFTNGP12.phx.gbl...

Shawn Corey [MSFT]

unread,
Sep 1, 2004, 1:31:18 PM9/1/04
to
If the cert was install with the key marked as exportable than on Windows
2000 or above you could open the Certificates snap-in in MMC and point to
either the current user if the cert was installed into the current users
store or the Local machine if that's where it is. Then goto
Personal/Certificates in the tree and right click on the cert you want and
select All Tasks/Export. If the key is marked as exportable an option will
be presented in the wizard to export the private key, selecting this option
automatically make the output a PFX file. Then just finish the wizard
selecting the password and filename and that should do it. If the key is not
marked as exportable and there is not an existing PFX then you would have to
get a new cert and key, that is marked as exportable or already in a PFX, to
use the option of loading from a file.

--
Thanks,
Shawn

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


"Kim Madsen" <k...@microsoft.com> wrote in message
news:eaPPbPCk...@TK2MSFTNGP12.phx.gbl...

0 new messages