473,387 Members | 1,517 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Digital Signature

Kim
I have a .NET service sending mails using CDOEX.

These mails I need to sign. I got a tip that I should use CAPICOM. That
worked
fine sending a mail with signature.

BUT the problem is that I have to type the password for my certificate every
time my program signs a mail :o(

My program is a windows service running on a server so typing passwords is
bad.

Then I got a new tip, I should use CryptoAPI instead of CAPICOM.

I think I have solved the CryptoAPI mystic and got my certificate, signed my
body of the mail and got the hash for it. But I don't know how to get my
signed code into the mail?

The code looks like this, and gives this error when the outlook client
reseive the mail:

Error: Can't open this item. Your Digital ID name can not be found by the
underlying security system.

This takes a byte array that I send from my CryptoAPI code.
Code:

private void SendMail(byte[] byteSignature)
{
CDO.IBodyPart oBodyPart;
ADODB.Fields cFields;
ADODB.Stream oStream;

// set sender, recipient, and subject.
oMessage = new CDO.Message();

oMessage.To = "re**********@Domain.dk";
oMessage.Subject = "Test Mail";
oMessage.Fields["urn:schemas:mailheader:date"].Value = DateTime.UtcNow;
oMessage.Fields.Update();

oMessage.From = "my*****@domain.dk";

oBodyPart = oMessage.BodyPart.AddBodyPart(1);
cFields = oBodyPart.Fields;

cFields["urn:schemas:mailheader:content-type"].Value =
CDO.CdoContentTypeValues.cdoTextPlain;
cFields.Update();

oStream = oBodyPart.GetDecodedContentStream();
oStream.WriteText("Hello this is some test text",0);
oStream.Flush();

//
//
// Start the new message
//
//
CDO.Message oSignedMsg = new CDO.Message();
CDO.IBodyPart oBodyPart2;
ADODB.Fields cFields2;
ADODB.Stream oStream2;

oSignedMsg.From = "My*****@domain.dk";

// 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 = oMessage.To;
oSignedMsg.CC = oMessage.CC;
oSignedMsg.Subject = oMessage.Subject;

oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;

cFields2["urn:schemas:mailheader:content-type"].Value =
oMessage.BodyPart.BodyParts[1].Fields["urn:schemas:mailheader:content-type"].Value;
cFields2.Update();

// Attach the signature and let CDO base64 encode it
oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;
oBodyPart2.Fields["urn:schemas:mailheader:content-type"].Value =
"application/x-pkcs7-signature\rName = " + '\u0022' + "smime.p7s" + '\u0022'
+ "";

oBodyPart2.Fields["urn:schemas:mailheader:content-transfer-encoding"].Value =
"base64";
oBodyPart2.Fields["urn:schemas:mailheader:content-disposition"].Value =
"attachment;\rFileName=" + '\u0022' + "smime.p7s" + '\u0022' + "";
cFields2.Update();
//
oStream2 = oBodyPart2.GetDecodedContentStream();
oStream2.Type = ADODB.StreamTypeEnum.adTypeBinary;
oStream2.Write (byteSignature);
oStream2.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["urn:schemas:mailheader:content-type"].Value =
"multipart/signed;\rprotocol=" + '\u0022' + "application/x-pkcs7-signature" +
'\u0022' + ";\rmicalg=SHA1;";

oSignedMsg.Fields.Update();

oMessage = oSignedMsg;
oMessage.Send();
}
Jul 21 '05 #1
12 10628
Hi

We have reviewed this issue and are currently researching on it. We will
update you ASAP. Thanks for your patience!

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

Jul 21 '05 #2
Hello,
Based on my understanding, you are trying to send encrypted email from
UserA to UserB, but get following error in UserB.
Error: Can't open this item. Your Digital ID name can not be found by the
underlying security system.

This error indicates that the recipient(s) that does not have a Digital ID
should either obtain one or an unencrypted message should be sent. The
certificates you have for the recipients listed are not valid. They may
have expired, may be the wrong type, or may not be supported by your
security policy. You will need to get/set new certificates from/to the
recipients so that the encrypted message could be decrypted successfully.
Best regards,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #3
Kim
Hello,

My Certificate is working perfect.

If I use CAPICOM to send a Sign Mail there is no problem.

To test it I send the mail to my self and I worked perfect with CAPICOM, but
with my code using CryptoAPI + the code here I got the error.

I had talked to some CryptoAPI guys and they say that my CryptoAPI code
should be fine but if you think my Mail code is correct you can se my
CryptoAPI code.

Best Regards

Kim

"Rhett Gong [MSFT]" wrote:
Hello,
Based on my understanding, you are trying to send encrypted email from
UserA to UserB, but get following error in UserB.
Error: Can't open this item. Your Digital ID name can not be found by the
underlying security system.

This error indicates that the recipient(s) that does not have a Digital ID
should either obtain one or an unencrypted message should be sent. The
certificates you have for the recipients listed are not valid. They may
have expired, may be the wrong type, or may not be supported by your
security policy. You will need to get/set new certificates from/to the
recipients so that the encrypted message could be decrypted successfully.
Best regards,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #4
Please post out your code and let me know which line fails.

Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #5
Kim
There is no error exception in the code, it compiles and run perfectly no
errors.

The error comes when the receiver of the mail tryes to open the mail and
outlook want to open the mail.

The Crypto code:

Just put it into a C# form:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
//using System.Text;

namespace SecuritySample
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
CDO.Message oMessage = new CDO.Message();

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{
SendMail();
}

const uint CERT_KEY_PROV_INFO_PROP_ID = 2;
const uint ALG_CLASS_HASH = (4 << 13);
const uint ALG_TYPE_ANY = 0;
const uint ALG_SID_SHA = 4;
const uint CALG_SHA = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA);
const uint AT_SIGNATURE = 2;
const uint PP_KEYEXCHANGE_PIN = 32;
const uint PP_SIGNATURE_PIN = 33;
const uint CERT_KEY_PROV_HANDLE_PROP_ID = 1;
const uint CERT_STORE_NO_CRYPT_RELEASE_FLAG = 1;
const uint X509_ASN_ENCODING = 0x00000001;
const uint PKCS_7_ASN_ENCODING = 0x00010000;

[DllImport("crypt32.dll", SetLastError=true)]
public static extern IntPtr CertDuplicateCertificateContext(
IntPtr pCertContext
);

[DllImport("crypt32.dll", SetLastError=true)]
public static extern IntPtr CertEnumCertificatesInStore(
IntPtr hCertStore,
IntPtr pPrevCertContext
);
[DllImport("crypt32.dll", SetLastError=true)]
public static extern IntPtr CertOpenSystemStore(
IntPtr hprov,
string szSubsystemProtocol
);

[DllImport("crypt32.dll", SetLastError=true)]
public static extern bool CertGetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
IntPtr pvData,
ref uint pcbData);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptAcquireContext(
ref IntPtr phProv,
string pszContainer,
string pszProvider,
uint dwProvType,
uint dwFlags);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptCreateHash(
IntPtr hProv,
int Algid,
IntPtr hKey,
uint dwFlags,
ref IntPtr phHash);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptHashData(
IntPtr hHash,
IntPtr pbData,
uint dwDataLen,
uint dwFlags);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptSetProvParam(
IntPtr hProv,
uint dwParam,
IntPtr pbData,
uint dwFlags
);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptSignHash(
IntPtr hHash,
uint dwKeySpec,
string sDescription,
uint dwFlags,
IntPtr pbSignature,
ref uint pdwSigLen
);

[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptDestroyHash(
IntPtr hHash
);
[DllImport("Advapi32.dll", SetLastError=true)]
public static extern bool CryptReleaseContext(
IntPtr hProv,
uint dwFlags
);

[DllImport("Crypt32.dll", SetLastError=true)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
uint dwFlags,
IntPtr pvData
);

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct CRYPT_KEY_PROV_INFO
{
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszContainerName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszProvName;

// public IntPtr pwszContainerName;
// public IntPtr pwszProvName;

public uint dwProvType;
public uint dwFlags;
public uint cProvParam;
public uint rgProvParam;
public uint dwKeySpec;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CRYPTOAPI_BLOB
{
public int cbData;
public IntPtr pbData;
}

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct CRYPT_ALGORITHM_IDENTIFIER
{
[MarshalAs(UnmanagedType.LPStr)]
public string pszObjId;
public CRYPTOAPI_BLOB Parameters;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CRYPT_SIGN_MESSAGE_PARA
{
public UInt32 cbSize;
public UInt32 dwMsgEncodingType;
public IntPtr pSigningCert;
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
public IntPtr pvHashAuxInfo;
public UInt32 cMsgCert;
public IntPtr rgpMsgCert;
public UInt32 cMsgCrl;
public IntPtr rgpMsgCrl;
public UInt32 cAuthAttr;
public IntPtr rgAuthAttr;
public UInt32 cUnauthAttr;
public IntPtr rgUnauthAttr;
public UInt32 dwFlags;
public UInt32 dwInnerContentType;
public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
public IntPtr pvHashEncryptionAuxInfo;
}

[DllImport("Crypt32.dll", EntryPoint="CryptSignMessage")]
public static extern bool CryptSignMessage(
ref CRYPT_SIGN_MESSAGE_PARA pSignPara,
bool fDetachedSignature,
UInt32 cToBeSigned,
string[] rgpbToBeSigned,
int[] rgcbToBeSigned,
IntPtr pbSignedBlob,
ref UInt32 pcbSignedBlob);

private void HandleError(string s) {throw new Exception(s);}

IntPtr GetCertificate()
{
IntPtr hCertStore = CertOpenSystemStore(IntPtr.Zero, "MY");
// Hvis pointeren er = 0 SÃ¥ kunne den ikke finde STOREN
if (hCertStore.ToInt32() == 0)
{
MessageBox.Show("CertOpenSystemStore failed: " +
Marshal.GetLastWin32Error().ToString());
return System.IntPtr.Zero ;
}
IntPtr pCertContext = CertEnumCertificatesInStore(hCertStore, IntPtr.Zero);
IntPtr tmp = CertDuplicateCertificateContext(pCertContext);
// Sender en pointer til det første Certificat i MY STOREen
//signHash(tmp);
return tmp;
}

byte[] signHash(string BodyText)
{
IntPtr pCert = GetCertificate();

CRYPT_KEY_PROV_INFO pKeyProvInfo = new CRYPT_KEY_PROV_INFO();
IntPtr pbKeyProvInfo=IntPtr.Zero;
uint cbKeyProvInfo=0;
IntPtr hProv = IntPtr.Zero;
IntPtr hHash = IntPtr.Zero;
IntPtr pbSignature = IntPtr.Zero;
uint dwSigLen=0;

// Call method to get size of buffer. The number of bytes needed goes
into cbKeyProvInfo
IntPtr Tmp = IntPtr.Zero;
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, Tmp,
ref cbKeyProvInfo);

// Allocate needed memory and call again with the correct buffer
preallocated
pbKeyProvInfo = Marshal.AllocHGlobal(new IntPtr(cbKeyProvInfo));

if (!CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID,
pbKeyProvInfo, ref cbKeyProvInfo))
HandleError("CertGetCertificateContextProperty failed");

pKeyProvInfo = (CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(pbKeyP rovInfo,
typeof(CRYPT_KEY_PROV_INFO));

string name = pKeyProvInfo.pwszProvName;
string cont = pKeyProvInfo.pwszContainerName;
if(name != "CRYPTOMATHiC RSA Full Provider 1.2")
return null;

if(!CryptAcquireContext(ref hProv,
//pKeyProvInfo.pwszContainerName,
cont,
//pKeyProvInfo.pwszProvName,
name,
pKeyProvInfo.dwProvType,
pKeyProvInfo.dwFlags))
HandleError("CryptAcquireContext failed");

IntPtr ProvData = Marshal.StringToHGlobalAnsi("Password");
if(pKeyProvInfo.dwKeySpec==AT_SIGNATURE)
{
if(!CryptSetProvParam(hProv, PP_SIGNATURE_PIN, ProvData, 0))
{
//Marshal.FreeHGlobal(Data);
HandleError("CryptSetProvParam failed");
}
}
else
{
if(!CryptSetProvParam(hProv, PP_KEYEXCHANGE_PIN, ProvData, 0))
{
//Marshal.FreeHGlobal(Data);
HandleError("CryptSetProvParam failed");
}
}
//Marshal.FreeHGlobal(Data);

CertSetCertificateContextProperty(pCert, CERT_KEY_PROV_HANDLE_PROP_ID,
CERT_STORE_NO_CRYPT_RELEASE_FLAG, hProv);
CRYPT_SIGN_MESSAGE_PARA signParams;
signParams = new CRYPT_SIGN_MESSAGE_PARA();
signParams.cbSize = (uint) Marshal.SizeOf(typeof(CRYPT_SIGN_MESSAGE_PARA));
signParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
signParams.pSigningCert = pCert;
signParams.HashAlgorithm.pszObjId = "1.2.840.113549.1.1.5";
signParams.HashAlgorithm.Parameters.cbData = 0;
signParams.pvHashAuxInfo = new IntPtr(0);
signParams.cMsgCert = 1;
signParams.rgpMsgCert = Marshal.AllocCoTaskMem ( Marshal.SizeOf
(typeof(IntPtr)));
Marshal.StructureToPtr (pCert, signParams.rgpMsgCert, true);
signParams.cMsgCrl = 0;
signParams.rgpMsgCrl = new IntPtr(0);
signParams.cAuthAttr = 0;
signParams.rgAuthAttr = new IntPtr(0);
signParams.cUnauthAttr = 0;
signParams.rgUnauthAttr = new IntPtr(0);
signParams.dwFlags = 0;
signParams.dwInnerContentType = 0;

string[] ConvertedString = {BodyText};
int[] sizes = {ConvertedString[0].Length};
CryptSignMessage (ref signParams, true, 1, ConvertedString, sizes,
IntPtr.Zero, ref dwSigLen);
pbSignature= Marshal.AllocHGlobal((int)dwSigLen);
CryptSignMessage (ref signParams, true, 1, ConvertedString, sizes,
pbSignature, ref dwSigLen);

byte[] output = new byte[dwSigLen];
Marshal.Copy(pbSignature,output,0,Convert.ToInt32( dwSigLen));
try
{
//SendMail(output);
return output;
}
catch(System.Exception ex)
{
MessageBox.Show(ex.Message);
}

if(!CryptReleaseContext(hProv,0))
HandleError("CryptReleaseContext failed");

Marshal.FreeHGlobal(pbKeyProvInfo);
Marshal.FreeHGlobal(pbSignature);
return null;
}

private void SendMail()
{
CDO.IBodyPart oBodyPart;
ADODB.Fields cFields;
ADODB.Stream oStream;

// set sender, recipient, and subject.
oMessage = new CDO.Message();
oMessage.To = "my****@domain.com";
oMessage.Subject = "Test Mail";
oMessage.Fields["urn:schemas:mailheader:date"].Value = DateTime.UtcNow;
// oUtilities.LocalTimeToUTCTime(DateTime.Now);
oMessage.TextBody = "Hello this is a test mail";
oMessage.From = "my****@domain.com";
oMessage.Fields.Update();

oBodyPart = oMessage.BodyPart.AddBodyPart(1);
cFields = oBodyPart.Fields;
//cFields[CDO.CdoMailHeader.cdoContentType].Value =
CDO.CdoContentTypeValues.cdoTextPlain;
cFields["urn:schemas:mailheader:content-type"].Value =
CDO.CdoContentTypeValues.cdoTextPlain;
cFields.Update();

oStream = oBodyPart.GetDecodedContentStream();
oStream.WriteText("Hello This is at test message :o)",0);
oStream.Flush();

//
//
// Start the new message
//
//
CDO.Message oSignedMsg = new CDO.Message();
CDO.IBodyPart oBodyPart2;
ADODB.Fields cFields2;
ADODB.Stream oStream2;

// set the from field based off of the selected certificate
oSignedMsg.From = "my****@domain.com";
oSignedMsg.DataSource.OpenObject(oMessage,
CDO.CdoInterfaces.cdoIMessage);
// 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 = oMessage.To;
oSignedMsg.CC = oMessage.CC;
oSignedMsg.Subject = oMessage.Subject;

oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;
//cFields2[CDO.CdoMailHeader.cdoContentType].Value =
oMessage.BodyPart.BodyParts[1].Fields[CDO.CdoMailHeader.cdoContentType].Value;
cFields2["urn:schemas:mailheader:content-type"].Value =
oMessage.BodyPart.BodyParts[1].Fields["urn:schemas:mailheader:content-type"].Value;
cFields2.Update();

// Attach the signature and let CDO base64 encode it
oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;
oBodyPart2.Fields["urn:schemas:mailheader:content-type"].Value =
"application/x-pkcs7-signature\rName = " + '\u0022' + "smime.p7s" + '\u0022'
+ "";
oBodyPart2.Fields["urn:schemas:mailheader:content-transfer-encoding"].Value = "base64";
oBodyPart2.Fields["urn:schemas:mailheader:content-disposition"].Value =
"attachment;\rFileName=" + '\u0022' + "smime.p7s" + '\u0022' + "";
cFields2.Update();
//
oStream2 = oBodyPart2.GetDecodedContentStream();
oStream2.Type = ADODB.StreamTypeEnum.adTypeBinary;
oStream2.Write (byteSignature);

oStream2.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["urn:schemas:mailheader:content-type"].Value =
"multipart/signed;\rprotocol=" + '\u0022' + "application/x-pkcs7-signature" +
'\u0022' + ";\rmicalg=SHA1;";
oSignedMsg.Fields.Update();
oMessage = oSignedMsg;

//oMessage.Send();
oSignedMsg.Send();
}
}
}

Jul 21 '05 #6
Hello Kim,
Are you sure your code you posted can work perfectly?
I found this line oStream2.Write (byteSignature); seems you did not declare
byteSignature anywhere and you did not use your cert to sign the textbody
before sending them.

I am currently trying to make your code work in my side and i will update
you later.

Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #7
Kim
Hello Rhett Gong,

You say that you would update me later when you had something up and
running, what happen? I haven't heard from you!

It would be nice if you could find a solution for me.

Thanks

Kim

"Rhett Gong [MSFT]" wrote:
Hello Kim,
Are you sure your code you posted can work perfectly?
I found this line oStream2.Write (byteSignature); seems you did not declare
byteSignature anywhere and you did not use your cert to sign the textbody
before sending them.

I am currently trying to make your code work in my side and i will update
you later.

Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #8
Hi Kim,

We are really sorry for the late response. Ray is out of office and will be
back on next Monday. I will look for somebody look into it first.

Thanks very much for your understanding.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
Register to Access MSDN Managed Newsgroups!
-http://support.microsoft.com/default.aspx?scid=/servicedesks/msdn/nospam.as
p&SD=msdn

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

Jul 21 '05 #9
Hi Kim,

I'm checked your code. Just as Rhett suggested, I didn't find the
declaration of it in the code you have provided. Is it the array which
contains the byte array of email signature? Could you provide us with more
information?

Here I think you have to call signHash to sign the body text before
assigning it directly to the oMessage.TextBody property.

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

Jul 21 '05 #10
Hello Kim,
Sorry for the late response.

I tried your code in my machine but it failed to recognize variable
"byteSignature". Could you post your code which is used to fill the
"byteSignature" so that I can repro your problem in my side and post my
suggestion after doing some research?

Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights.
Please reply to newsgroups only. Thanks.

Jul 21 '05 #11
Hi Kim,

I found your posts by doing a search on goolge and went through your code as
I need to do the same type of thing. Yes you did not declare byteSignature
but I saw your byte[] should come from the signHash function.
I then ran the code and got an error in the client email application.
Something about a problem with the headers of the email. I then did some
diging, hacking, cracking and reading and found the problem. Since you did
all the work in getting the API to work properly in c# I only saw it fit to
give you my final solution. This function will replace your SendMail
function...

private void SendMail(string to, string from, string cc, string subject,
string body)
{
CDO.Message oSignedMsg = new CDO.Message();
oSignedMsg.From = "fa***@shweetthings.com";
oSignedMsg.To = to;
if(cc != null && cc.Trim() != "")
{
oSignedMsg.CC = cc;
}
oSignedMsg.Subject = subject;
oSignedMsg.BodyPart.ContentMediaType = "multipart/signed;\rprotocol=" +
'\u0022' + "application/x-pkcs7-signature" + '\u0022' + ";\rmicalg=SHA1;";

CDO.IBodyPart oBodyPart =
oSignedMsg.BodyPart.AddBodyPart(oSignedMsg.BodyPar t.BodyParts.Count + 1);
oBodyPart.ContentMediaType = "multipart/mixed";

CDO.IBodyPart oBodyPart2 =
oBodyPart.AddBodyPart(oBodyPart.BodyParts.Count + 1);
oBodyPart2.ContentMediaType = "text/plain;charset=\"iso-8859-1\"";
ADODB.Stream oStream = oBodyPart2.GetDecodedContentStream();
oStream.WriteText(body, 0);
oStream.Flush();
oStream.Close();

CDO.IBodyPart oSigniturePart =
oSignedMsg.BodyPart.AddBodyPart(oSignedMsg.BodyPar t.BodyParts.Count + 1);
oSigniturePart.ContentMediaType = "application/x-pkcs7-signature";
oSigniturePart.ContentTransferEncoding = "base64";
oSigniturePart.Fields["urn:schemas:mailheader:content-disposition"].Value
= "attachment;\rFileName=" + '\u0022' + "smime.p7s" + '\u0022' + "";
oSigniturePart.Fields.Update();

oStream = oSignedMsg.GetStream();
string messageToSign = oStream.ReadText(oStream.Size);
byte[] byteSignature = signHash(messageToSign);

oStream = oSigniturePart.GetDecodedContentStream();
oStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
oStream.Write(byteSignature);
oStream.Flush();
oStream.Close();

oSignedMsg.Send();
}

The problem, simply, was with your bodyparts, when attaching the signiture
this must be in a new bodypart it seems and your mail body/s should form
part of the main bodypart... There is one more problem though. The mail is
not signed 100% correctly, the certificate is attached and content signed,
but it seems that when it is opened the Mail client reports it as being
tampered with... If you find a solution to that, please let me know... I now
have a nice little library to sign the messages, if you would like me to
attach the whole project please don't hesitate to ask...

Please let me know if this works for you or not...

Regards,
Fanie Oosthuysen

"Kim" <ev***@noemail.nospam> wrote in message
news:79**********************************@microsof t.com...
Hello Rhett Gong,

You say that you would update me later when you had something up and
running, what happen? I haven't heard from you!

It would be nice if you could find a solution for me.

Thanks

Kim

"Rhett Gong [MSFT]" wrote:
Hello Kim,
Are you sure your code you posted can work perfectly?
I found this line oStream2.Write (byteSignature); seems you did not declare byteSignature anywhere and you did not use your cert to sign the textbody before sending them.

I am currently trying to make your code work in my side and i will update you later.

Thanks,
Rhett Gong [MSFT]
Microsoft Online Partner Support

This posting is provided "AS IS" with no warranties, and confers no rights. Please reply to newsgroups only. Thanks.

Jul 21 '05 #12
Hi Kim,

I found your posts by doing a search on goolge and went through your code as
I need to do the same type of thing. Yes you did not declare byteSignature
but I saw your byte[] should come from the signHash function.
I then ran the code and got an error in the client email application.
Something about a problem with the headers of the email. I then did some
diging, hacking, cracking and reading and found the problem. Since you did
all the work in getting the API to work properly in c# I only saw it fit to
give you my final solution. This function will replace your SendMail
function...

private void SendMail(string to, string from, string cc, string subject,
string body)
{
CDO.Message oSignedMsg = new CDO.Message();
oSignedMsg.From = "fa***@shweetthings.com";
oSignedMsg.To = to;
if(cc != null && cc.Trim() != "")
{
oSignedMsg.CC = cc;
}
oSignedMsg.Subject = subject;
oSignedMsg.BodyPart.ContentMediaType = "multipart/signed;\rprotocol=" +
'\u0022' + "application/x-pkcs7-signature" + '\u0022' + ";\rmicalg=SHA1;";

CDO.IBodyPart oBodyPart =
oSignedMsg.BodyPart.AddBodyPart(oSignedMsg.BodyPar t.BodyParts.Count + 1);
oBodyPart.ContentMediaType = "multipart/mixed";

CDO.IBodyPart oBodyPart2 =
oBodyPart.AddBodyPart(oBodyPart.BodyParts.Count + 1);
oBodyPart2.ContentMediaType = "text/plain;charset=\"iso-8859-1\"";
ADODB.Stream oStream = oBodyPart2.GetDecodedContentStream();
oStream.WriteText(body, 0);
oStream.Flush();
oStream.Close();

CDO.IBodyPart oSigniturePart =
oSignedMsg.BodyPart.AddBodyPart(oSignedMsg.BodyPar t.BodyParts.Count + 1);
oSigniturePart.ContentMediaType = "application/x-pkcs7-signature";
oSigniturePart.ContentTransferEncoding = "base64";
oSigniturePart.Fields["urn:schemas:mailheader:content-disposition"].Value
= "attachment;\rFileName=" + '\u0022' + "smime.p7s" + '\u0022' + "";
oSigniturePart.Fields.Update();

oStream = oSignedMsg.GetStream();
string messageToSign = oStream.ReadText(oStream.Size);
byte[] byteSignature = signHash(messageToSign);

oStream = oSigniturePart.GetDecodedContentStream();
oStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
oStream.Write(byteSignature);
oStream.Flush();
oStream.Close();

oSignedMsg.Send();
}

The problem, simply, was with your bodyparts, when attaching the signiture
this must be in a new bodypart it seems and your mail body/s should form
part of the main bodypart... There is one more problem though. The mail is
not signed 100% correctly, the certificate is attached and content signed,
but it seems that when it is opened the Mail client reports it as being
tampered with... If you find a solution to that, please let me know... I now
have a nice little library to sign the messages, if you would like me to
attach the whole project please don't hesitate to ask...

Please let me know if this works for you or not...

Regards,
Fanie Oosthuysen

"Kim" <ev***@noemail.nospam> wrote in message
news:E2**********************************@microsof t.com...
I have a .NET service sending mails using CDOEX.

These mails I need to sign. I got a tip that I should use CAPICOM. That
worked
fine sending a mail with signature.

BUT the problem is that I have to type the password for my certificate every time my program signs a mail :o(

My program is a windows service running on a server so typing passwords is
bad.

Then I got a new tip, I should use CryptoAPI instead of CAPICOM.

I think I have solved the CryptoAPI mystic and got my certificate, signed my body of the mail and got the hash for it. But I don't know how to get my
signed code into the mail?

The code looks like this, and gives this error when the outlook client
reseive the mail:

Error: Can't open this item. Your Digital ID name can not be found by the
underlying security system.

This takes a byte array that I send from my CryptoAPI code.
Code:

private void SendMail(byte[] byteSignature)
{
CDO.IBodyPart oBodyPart;
ADODB.Fields cFields;
ADODB.Stream oStream;

// set sender, recipient, and subject.
oMessage = new CDO.Message();

oMessage.To = "re**********@Domain.dk";
oMessage.Subject = "Test Mail";
oMessage.Fields["urn:schemas:mailheader:date"].Value = DateTime.UtcNow; oMessage.Fields.Update();

oMessage.From = "my*****@domain.dk";

oBodyPart = oMessage.BodyPart.AddBodyPart(1);
cFields = oBodyPart.Fields;

cFields["urn:schemas:mailheader:content-type"].Value =
CDO.CdoContentTypeValues.cdoTextPlain;
cFields.Update();

oStream = oBodyPart.GetDecodedContentStream();
oStream.WriteText("Hello this is some test text",0);
oStream.Flush();

//
//
// Start the new message
//
//
CDO.Message oSignedMsg = new CDO.Message();
CDO.IBodyPart oBodyPart2;
ADODB.Fields cFields2;
ADODB.Stream oStream2;

oSignedMsg.From = "My*****@domain.dk";

// 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 = oMessage.To;
oSignedMsg.CC = oMessage.CC;
oSignedMsg.Subject = oMessage.Subject;

oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;

cFields2["urn:schemas:mailheader:content-type"].Value =
oMessage.BodyPart.BodyParts[1].Fields["urn:schemas:mailheader:content-type"]
..Value; cFields2.Update();

// Attach the signature and let CDO base64 encode it
oBodyPart2 = oSignedMsg.BodyPart.AddBodyPart(1);
cFields2 = oBodyPart2.Fields;
oBodyPart2.Fields["urn:schemas:mailheader:content-type"].Value =
"application/x-pkcs7-signature\rName = " + '\u0022' + "smime.p7s" + '\u0022' + "";

oBodyPart2.Fields["urn:schemas:mailheader:content-transfer-encoding"].Value
= "base64";
oBodyPart2.Fields["urn:schemas:mailheader:content-disposition"].Value = "attachment;\rFileName=" + '\u0022' + "smime.p7s" + '\u0022' + "";
cFields2.Update();
//
oStream2 = oBodyPart2.GetDecodedContentStream();
oStream2.Type = ADODB.StreamTypeEnum.adTypeBinary;
oStream2.Write (byteSignature);
oStream2.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["urn:schemas:mailheader:content-type"].Value =
"multipart/signed;\rprotocol=" + '\u0022' + "application/x-pkcs7-signature" + '\u0022' + ";\rmicalg=SHA1;";

oSignedMsg.Fields.Update();

oMessage = oSignedMsg;
oMessage.Send();
}

Jul 21 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Kim H Madsen | last post by:
I have created a .Net Service that is sending mails using SMTP Server/Exchange Server how do i put in a Digital Signature so the reciver is 100% sure that the mail i from the owner of Server where...
7
by: Guangxi Wu | last post by:
Hi all, Happy New Year. I am using SignedXML and an X509 certificate to digitally sign a SOAP message body and put the signature in the SOAP header for a B2B business application. Can you...
5
by: John Campbell | last post by:
Hi everyone I've been doing my best to understand the specifics of implimentating XML Digital Signatures, but I seem to be missing a fundamental concept. Let me start with a description of the...
0
by: CLarkou | last post by:
I bought a digital signature for my MSaccess application in Office 2003. I select TOOLS\Digital Signatures in Visual Basic Editor and I am not able to see my digital signature in the available...
2
by: Martin Høst Normark | last post by:
Hi everyone Has anyone got the least experience in integrating the Digital Signature with an ASP.NET Web Application? Here in Denmark, as I supose in many other countries, they're promoting...
6
by: Matt Frame | last post by:
I have a client that has asked us to get a digital signature certificate and start digitally signing all files we pass between each other. I have heard of the subject and know about the certs but...
1
by: claudia_usa | last post by:
Hello, Does anyone know how to include the signature field when creating PDF crystal reports with VB.net? Our intension is to allow the user to generate the report with their digital signature...
0
by: Geagleeye | last post by:
Hi everyone. I have some vba code to generate a pdf document through word, and add also digital signature. My problem is : how can i change the way the signature layout, it always show the...
3
by: itcoll | last post by:
i have wriiten java code for client server communication - the client sends a digital signature and the server verifies it using the public key .I have sent the signature as a string from the client...
3
by: tmoloy | last post by:
I am using RFID tags to store some data which will then be read by a 3rd party. I need to include a digital signature (or some variation) along with the data so that the 3rd party can verify the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.