Digitally sign files from within a web application

J

Joao Maia

Hi there,

I am a newbie to the security framework of .net and to digital
signatures, and I need some help regarding signing files in .net.

Here's my problem: I have a web application developed in asp.net (with
..net framework 1.1). This web app has a support database and can access
files that are stored on a physical drive in some server (pretty much
any kind of file, although the most accessed are .doc, .xls, .ppt,
..pdf, .tif). What I want to do now is to add some digital signature
functionality to that app. The users must be able to choose a file and
digitally sign it with a certificate stored locally (either on their
machine or in a smartcard, for example). And the signature must be
valid outside my app, for example if any user opens a doc file in Word
directly from its location on the physical disk, Word must still
recognize that the file is signed.
From my point of view several problems rise here:

- I need to pass the file from server to client in order to sign it,
since the private key is stored on the certificate, which is on the
client. Since the files can be big, and for performance issues, I think
it's better to pass a hash of the file and sign the hash. Is this
correct ? Does the .net framework provide any way of building a hash
for this purpose ? I've been looking at the HashAlgorithm class and
ComputeHash method. Is this it ?

- I need to sign the file with the certificate on the client side. Here
I'm completely at loss, since I haven't yet found any methods to sign
files or a stream or a byte array with a certificate. I've been
browsing through X509Certificate class, but I've got no clues...

- Finally, after the hash is signed, I need to pass it back to the
server and somehow, to store it with the original file, so that the
signature is recongnized outside my app. Here I'm also at a loss. I
don't even know if there's a way to do this.

So I was wondering if any of you can help me with this problem. I'm not
quite sure if the approach I mentioned is the best one or not. Maybe
there's some easier way to do it, but as I told you, this is new
terrain for me, I've never had to deal with certificates and signatures
before, so I really don't know where to start. Any help on this will be
greatly appreciated.

Thanks in advance.

Cheers from Portugal,

Joao Maia
 
J

Joe Kaplan \(MVP - ADSI\)

The first thing you'll need to figure out is how you are going to execute
code on the user's machine. Will you use an ActiveX control or a
downloadable .NET WinForms control? You could also install something on
their machine or use ClickOnce deployment if you can use .NET 2.0. However,
you can't do this only in server-side code.

If you can, I'd recommend using the SignCms Class in .NET 2.0 for actually
packaging up the signed data into a standard PKCS7 signed data structure,
but you could probably use the RSA classes directly. This all presupposes
that your deployment model of your client side code will allow you to use
..NET in the first place.

Joe K.
 
J

Joao Maia

Hi, thanks for your reply.

Regarding the execution of code on the client site, I was thinking of
using an ActiveX control. Eventually I thought about using a .NET
Winforms control, but the issue here is that I'm not able to use .NET
2.0 because we can't migrate the code we have now from .NET 1.1.

Joao Maia
 
J

Joe Kaplan \(MVP - ADSI\)

In an ActiveX control, you'd probably want to use CAPICOM to do the signing,
but you'd have to make sure that's installed in order to use it. You could
also call the cryptoapi directly.

With a .NET control in 1.1, you don't have the CMS support by you can sign
data. There is a SignHash method on RSACryptoServiceProvider, so if you can
pass the hash of the data to the client, you could potentially use that.

Best of luck,

Joe K.
 
E

Eugene Mayevski

Hello!
You wrote on 26 Jul 2006 02:42:32 -0700:

JM> machine or in a smartcard, for example). And the signature must be
JM> valid outside my app, for example if any user opens a doc file in Word
JM> directly from its location on the physical disk, Word must still
JM> recognize that the file is signed.

This is not possible: most file formats don't include support for digital
signatures and if you sign the file, you will have one of the following:
either a detached signature (kept in a separate file) or a single file in
some format which is not readable by the applications that are intended to
read the document. For example, you can sign using PKCS#7, but then you end
up with one of the variants that I've mentioned.

With best regards,
Eugene Mayevski
http://www.SecureBlackbox.com - the comprehensive component suite for
network security
 
J

Joao Maia

Eugene said:
Hello!
You wrote on 26 Jul 2006 02:42:32 -0700:

JM> machine or in a smartcard, for example). And the signature must be
JM> valid outside my app, for example if any user opens a doc file in Word
JM> directly from its location on the physical disk, Word must still
JM> recognize that the file is signed.

This is not possible: most file formats don't include support for digital
signatures and if you sign the file, you will have one of the following:
either a detached signature (kept in a separate file) or a single file in
some format which is not readable by the applications that are intended to
read the document. For example, you can sign using PKCS#7, but then you end
up with one of the variants that I've mentioned.

With best regards,
Eugene Mayevski
http://www.SecureBlackbox.com - the comprehensive component suite for
network security

Hi,

Thanks for your reply.

I understand that, but what about file formats that do include support
for digital signatures, such as Word or PDF ? To be honest, the only
file formats I'm interested in to support this functionality are PDF,
Word, Excel, Powerpoint. For the rest of the file formats, I really am
not worried whether the signature is recognized outside my app, or not.

Now with those that do include support for signatures, my question is
if it is possible to create a hash of this file, sign it, and then
somehow merge the signed hash back into the original file so that the
application dealing with the file recognizes that it is signed. I've
noticed that, for example, the Word API has something like
Word.ActiveDocument.Signatures collection and that you can actually add
items to that collection, but I don't know what kind of objects I can
add to that collection and even if I did know I figure that I need to
use the same method Word uses to sign files (same algorithm for the
hash, same way of signing), otherwise the signature would not be
recognized. Is this correct ? Or am I still missing something here ?

Thanks once again,

Joao Maia
 
E

Eugene Mayevski

Hello!
You wrote on 27 Jul 2006 02:11:27 -0700:

JM> I understand that, but what about file formats that do include support
JM> for digital signatures, such as Word or PDF ? To be honest, the only
JM> file formats I'm interested in to support this functionality are PDF,
JM> Word, Excel, Powerpoint. For the rest of the file formats, I really am
JM> not worried whether the signature is recognized outside my app, or not.

MS formats are closed, and, moreover, they are different between versions.

JM> Now with those that do include support for signatures, my question is
JM> if it is possible to create a hash of this file, sign it, and then
JM> somehow merge the signed hash back into the original file so that the
JM> application dealing with the file recognizes that it is signed.

As for PDF, this will be possible with SecureBlackbox 5.

JM> I've noticed that, for example, the Word API has something like
JM> Word.ActiveDocument.Signatures collection and that you can actually add
JM> items to that collection, but I don't know what kind of objects I can
JM> add to that collection and even if I did know I figure that I need to
JM> use the same method Word uses to sign files (same algorithm for the
JM> hash, same way of signing), otherwise the signature would not be
JM> recognized. Is this correct ? Or am I still missing something here ?

With MS tools the situation is quite complex: as the formats are closed,
it's hard to get any information about how to use the security with MS
documents.

With best regards,
Eugene Mayevski
http://www.SecureBlackbox.com - the comprehensive component suite for
network security
 
J

Joe Kaplan \(MVP - ADSI\)

Note that I had sort of assumed you were going to do some sort of detached
signature thing or use PKCS7 signed data in order to accomplish this. I
agree with Eugene that there is no clean way to provide general purpose
signing of arbitrary files without doing that.

Joe K.
 
J

Joao Maia

Hi again,

What if I sign the files themselves and not just a hash ? Is this
possible ? Can you sign a FileStream that's actually a doc document
(for example) with a certificate from a certificate store ? Will word
still recognize it as a signed file ? Or the FileStream will just be
encrypted in a way that the app (in this case word) won't recognize it
anymore as a word file ?

Anyway, what's this thing about PKCS#7 signed data ? I understand that
it is a RSA standard and tried reading the specification but I'm afraid
I did not understand it very well and how it can be used on a practical
situation. Correct me if I'm wrong but, from what I understood, after
signing you're supposed to have two files, one which is the original
and one with the signed digest. In this scenery, I can validate that
the file hasn't been messed with in my application by doing the hash of
the original file, decrypting the signed hash with the certificate
public key and comparing both hashes. But how can the original
application from which the file was originally created (Word in our
example), be able to recognize the signature ?

Once again thank you both for helping me and sorry for bothering you
with this.

Joao Maia
 
J

Joe Kaplan \(MVP - ADSI\)

PKCS7 is a standard developed by RSA that is useful for providing encryption
and signing capabilities to arbitrary data, primary using certificates and
RSA encryption/decryption.

Essentially, it uses ASN.1 and defined schema for specifying how to "wrap"
content with signature and encryption info. The enveloped data structure
solves the problem with encryption of how to specify the symmetric algorithm
used, where to store the encrypted symmetric key, who the message was
encrypted for, etc. With signed data, it specifies the certs used to sign
the data, the message hash, the data that was signed, etc. This saves you
from having to invent your own file format for doing all the same stuff and
allows clients that understand PKCS7 (like SMIME compatible email clients)
to exchange signed and encrypted content.

I actually don't know anything about how to encorporate signatures into file
formats that have built-in support for signatures like Word and PDF. Eugene
seems to have some code that supports this type of thing for PDF though.

Also, the way the SignData method on RSACryptoServiceProvider works is that
it does not change the underlying data being signed. It simply gives you a
binary blob of data with a signature based on the data you wanted signed and
the parameters you wanted to sign it with. This is essentially just a
detached signature. There seemed to be some misunderstanding on how it
worked based on your first paragraph.

Joe K.
 
J

Joao Maia

Thanks, I think I got the basic idea behind PKCS#7 now. Do you have any
idea regarding what kind of clients support this standard ?

Joao Maia
 
J

Joe Kaplan \(MVP - ADSI\)

Well, lots of email clients do. Outlook and Outlook Express come to mind.
I'm sure many others do as well.

I'm not sure if PKCS7 will work for you or not as I don't really understand
what it is that you are trying to do with the digital signatures on this
data.

Joe K.
 
J

Joao Maia

Basically, I'm part of a development team of a Document Management
Product. We want to add digital signature functionality to the
documents managed by our product. The purpose we are trying to achieve
is the usual for digital signatures: guaranteeing that the document is
not tampered with since the time it is signed, and if it is, invalidate
the signature. Since we deal with several types of documents, we need
to be able to sign at least the most used ones, from within our
application.
From what I've seen, most digital signatures in commonly used formats
such as pdf are PKCS#7 compliant, so I'm guessing that's the way to go.

jm
 
J

Joe Kaplan \(MVP - ADSI\)

If you used detached signatures, you could definitely use those signatures
in the context of the web application to show their signed status and verify
if the signatures were still valid, since you would presumably have control
over all this stuff. That would allow you to sign arbitrary content as
well. The downside would be that the signatures in your system would not be
stored directly in the actual files, but that could be a feature. :)

Joe K.
 
M

moises.cid

Joao Maia ha escrito:
Hi,

Thanks for your reply.

I understand that, but what about file formats that do include support
for digital signatures, such as Word or PDF ? To be honest, the only
file formats I'm interested in to support this functionality are PDF,
Word, Excel, Powerpoint. For the rest of the file formats, I really am
not worried whether the signature is recognized outside my app, or not.

Now with those that do include support for signatures, my question is
if it is possible to create a hash of this file, sign it, and then
somehow merge the signed hash back into the original file so that the
application dealing with the file recognizes that it is signed. I've
noticed that, for example, the Word API has something like
Word.ActiveDocument.Signatures collection and that you can actually add
items to that collection, but I don't know what kind of objects I can
add to that collection and even if I did know I figure that I need to
use the same method Word uses to sign files (same algorithm for the
hash, same way of signing), otherwise the signature would not be
recognized. Is this correct ? Or am I still missing something here ?

Thanks once again,

Joao Maia

Hi,

Joao here you have an example for signing a pdf file:

http://article.gmane.org/gmane.comp.windows.dotnet.itextsharp.general/12

In this sample you can sign the file from a a certificate stored in a
device like a hdd o smartcard, but it doesn't work if you have an
asp.net application.
I've the same problem that you, how can a client of an asp.net
application sign a pdf document using the certificate stored in the
"personal store"???

I've seen something about CAPICOM but I'm lost, can anybody help me?

Thanks
 
J

Joao Maia

Hi,

What I'm going to do is write a .NET Windows Form component (which I'm
going to host on Internet Explorer) to get a certificate from the
user's certificate store to sign my document.

To access certificate stores and X509 Certificates, and to digitally
sign data, there are several approaches:

1 - Use the support on .NET Framework 1.1 in
System.Security.Cryptography and
System.Security.Cryptography.X509Certificates namespaces.

The support for this is somewhat limited on these namespaces (it has
improved on .NET Framework 2.0, but I can't use that so that's out of
the question for me). So I tried approach number 2:

2 - Download Microsoft Web Services Enhancements (WSE) at

http://www.microsoft.com/downloads/...31-c3e7-420a-bc1e-ef18bab66122&displaylang=en

This has some improved functionality on certificates and certificate
stores, plus it includes many code samples on how to do basic things
such as opening a store and signing data

3 - If there's still something that you can't do with approach 2, you
must do it with CAPICOM (also downloadble from Microsoft). CAPICOM is a
COM wrapper for Microsoft's Win 32 Crypto API.

If there's still something you can't do with CAPICOM, then you'll have
to call the Crypto API directly through Platform Invoke (P/Invoke)

Check out these links, to know more about this:

http://www.c-sharpcorner.com/Upload...rticleID=cf900b08-35ed-4524-aeff-6806265a4196
http://www.c-sharpcorner.com/Code/2003/Jan/DigitalCertIII.asp

The problem I'm having right now is that I can't open a dialog for the
user to select the certificate because I'm getting the following error:

"That assembly does not allow partially trusted callers"

I figure this is happening because I'm calling some assembly that needs
special permissions to access the user's certificate store from a web
page, but still haven't been able to figure out what those permissions
are.

Hope I've been of some help... Let me know if you can solve your
problem or not.

Cheers from Portugal,

jm
 
D

Dominick Baier

Both CAPICOM and WSE3 demand full trust. Browser hosted controls don't get
FT by default.

The error you are seeing happens when a partially trusted client calls into
these DLLs.

You have to manually adjust the CAS Policy on every client to grant Full
Trust to your component - best by basing the policy on the strong name of
your component. You can use mscorcfg.msc or CasPol for this.

dominick
 
J

Joao Maia

[dominick]
You have to manually adjust the CAS Policy on every client to grant Full
Trust to your component - best by basing the policy on the strong name of
your component. You can use mscorcfg.msc or CasPol for this.

How do I do this ? What is mscorcfg.msc ? What is CasPol ?

Thanks,

jm
 
J

Joao Maia

Joao said:
[dominick]
You have to manually adjust the CAS Policy on every client to grant Full
Trust to your component - best by basing the policy on the strong name of
your component. You can use mscorcfg.msc or CasPol for this.

How do I do this ? What is mscorcfg.msc ? What is CasPol ?

Thanks,

jm

Ok, after searching for CasPol, I used it on my assembly with the
-addfulltrust option but it still doesn't work. Oh and my assembly is
strongly named.

My assembly (the user control hosted on IE) uses
Microsoft.Web.Services2.dll assembly from Microsoft WSE, so I ran
CasPol on that assembly as well, but I still get the same error
message.

Is there any way to know what is the assembly that is causing the
problem ?

jm
 
D

Dominick Baier

You may find it more intuitive to use the GUI

Adm. Tools -> .NET Framework Configuration

Runtime Security Policy -> Machine -> All Code

Create new Code group -> use strong name membership condition and assign
full trust.

I looked for a good walkthrough online meanwhile, but couldn't find something...maybe
someone else has a link?

dominick
Joao said:
[dominick]
You have to manually adjust the CAS Policy on every client to grant
Full Trust to your component - best by basing the policy on the
strong name of your component. You can use mscorcfg.msc or CasPol
for this.
How do I do this ? What is mscorcfg.msc ? What is CasPol ?

Thanks,

jm
Ok, after searching for CasPol, I used it on my assembly with the
-addfulltrust option but it still doesn't work. Oh and my assembly is
strongly named.

My assembly (the user control hosted on IE) uses
Microsoft.Web.Services2.dll assembly from Microsoft WSE, so I ran
CasPol on that assembly as well, but I still get the same error
message.

Is there any way to know what is the assembly that is causing the
problem ?

jm
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top