Update 2004-10-24: I will soon be adding some further notes to the
text below. Amongst the notes will be info on what happens when code you thought
you had signed is suddenly assumed by the security apparatus to be untrustable
merely because the certificate has since expired. In brief, be sure to review
the -t or -timestamp flags on signcode... This is once again obfuscated and
confusingly described, so it's taking me a while to get to the bottom of it. And
needless to say I'm not pleased that the default behavior of signcode is to
asume that the developer wants their code to break after one year.

Motivation and Overview

With the increased rigor of security in Visio 2003, there's more motivation
than ever to sign code. Unsigned VSLs and VBA projects cause Visio to bombard
users with macro security warnings (if security is set to "Medium"), or result
in outright silent non-operation of your code (if security is set to "High").

Unfortunately, the realm of code signing seems (to me at least) unnecessarily
cluttered with obfuscation to the point of being virtually incomprehensible to
normal mortals (as corroborated by the preponderance of mistaken info in the
usually-invaluable Google newsgroup searches).

The system is partly facilitated by Microsoft, using a patchwork of tools and
dialogs (not to mention the ever-popular inscrutably vague message boxes), with
an evolution of different schemes over just a few years. Meanwhile, the actual
security certificates that are key to this system have to be obtained from
third-party vendors who sell a wide array of security products, use different
terminology and are thoroughly unclear about which products do what.

Though I'm far from an authority on the subject, the following is at least a
step-by-step account of one way to chop through this jungle. This article is
primarily aimed at "the little guy (or gal)". I assume that readers who
are part of a large corporate IT shop already have a position on code signing,
and one or more people who know how to do it and administer a system for issuing
certificates and so on. But the individual or small-shop developers, for whom
Office Automation (and particularly Visio Automation) affords a superb
opportunity to quickly assemble highly-tailored solutions, may well find the
code-signing business mysterious and somewhat daunting.

Let's start with the concept of the certificate, then figure out how to get
one, and finally use it to actually sign some code. Editorial comments reserved
until the end (mostly).

Certificates

A certificate is a blob of data that contains a publisher name (for example
your name as a developer) and other identifying info, plus some encryption key
information. The certificate itself is encrypted in such a way that the
publisher info and the key info are inexorably glued together (ie: so that the
association of publisher Id and key info can't be faked).

These features so far merely provide a way to associate this info together,
to some level of confidence. The value comes when:

a) the certificate (and hence the identifying power) is provided by some
well-known trusted third party, and

b) this info is applied to encrypt and identify some other blob of
data, like an email message or some executable code like an application or DLL
("the code is signed with the certificate").

... which, in theory at least, allows a recipient of that message or code to
have some confidence that it did indeed come from whom it purports to come from.

What Users See: Security Warning Behavior

Windows applications can perform security checks before, for example, running
some VBA or addon code. If the code has been signed, and it's from a software
publisher on this machine's trusted list, then the operation proceeds and you as
a user don't see any special effect. If the code is not signed, or it's signed
by a publisher that is not on this user's trusted list, then you see one of
those ubiquitous Security Dialogs. The exact behavior varies, depending on the
security level you have set for the application:

Code Signature?

Publisher on Machine's
Trusted List?

App's Security Setting

Low

Medium

High

Yes

Yes

Operation proceeds

Operation proceeds

Operation proceeds

Yes

No

Operation proceeds

App presents warning dialog [1]

App presents warning dialog [1]

No

No

Operation proceeds

App presents warning dialog [1]

Operation fails, no warning dialog

[1] Depending on type of certificate, the
warning dialog may offer the user the option to "always trust software from
this publisher".
Checking this option adds the publisher to the user's trusted list.

Of special note are the two corner cases:

With Low security the app will run anything without warning. In a Visio
situation, this is a risky setting if you suspect that you or your users may
somehow obtain Visio docs that contain malicious code. If that's not the case,
then this setting is most convenient for development (even if alarming to IT
folks).

With High security, the app will basically ignore unsigned macros, addons
etc. For Visio developers, this setting is a significant pain for developing
code. It's worth noting that Visio is especially affected by code that doesn't
run, as it's common for Visio solutions to require addon functionality to
maintain the integrity of the drawing data as the user performs edits (a setup
that's perhaps quite different than with other Office apps). So to have the
security system shut off the functionality without any indication is pretty much
the same as a bug in the solution.

Medium security level is tolerable for developers to work with, but for users
still results in security warning dialogs for solution VBA, Addons or COM Addins
that haven't been signed by a trusted publisher. So there's considerable
motivation for the developer to sign the code.

So back to the story of certificates, code signing and so on.

Applying a Certificate's Key(s)

Included in a certificate are what's called a "public key", and optionally a
"private key".

A certificate for use by an author ("publisher") includes the private key,
which is used with an encryption tool to encrypt some other data, like an email
message or code. In that encryption process, the author's identifying info is
included. The objective of the encryption is not so much to keep the data
secret, but rather to glue the author's identifying info to that data in a
tamper-proof manner.

Later, when the encrypted code or email is received by a user, it comes with
the identifying and public-key portion of the certificate's data. This is used
by the user (or OS or whatever) to decrypt that code or email. In so
doing, the user sees the author's identifying info, and can make decisions about
whether to trust the attached data (believe the email, run the code) based on
that author's identity.

In passing we note a nifty and essential feature: the public key used to
decrypt the data is different from and doesn't reveal the private key that the
author used to encrypt it. Assuming the author keeps the private key secret,
this means that no one else can duplicate the author's signature.

Certificates for Authors

To sign code you need to obtain a certificate that identifies you and
includes the private key part of the data.

You can generate a certificate for yourself using the MakeCert.exe utility,
or you can obtain one from a Certificate Authority ("CA"), essentially a vendor
who sells certificates, such as Verisign.

Certificates from these different sources are equivalent in terms of their
data structure, but differ in the level of confidence they provide as to the
author they represent. If I create my own certificate, I can claim to be anybody
I want to. But other data in the certificate tells that this is a self-generated
certificate, validated by no other authority. Security warning dialogs warns
users of this situation.

A certificate vendor, such as Verisign or Thawte, offers a service which
includes investigating and validating your identity and trustworthiness. The
higher the level of scrutiny you request, the more you pay, and the higher the
level of trustworthiness of the resulting certificate that the vendor issues to
you.

Certificates you generate or buy are stored on your local machine (associated
with your username) -- we'll see the detail on this below.

As a User...

... you receive the public parts of certificate info in emails, web pages,
and along with signed code. Depending on your security settings, these may
trigger the all-too-familiar security dialog informing you of who the publisher
is for that code or data. When you OK one of those dialogs, you let the code or
whatever run once.

That dialog often provides a checkbox for "always trust this publisher". If
you check that box, then the certificate info for that publisher is saved by
your machine in your list of "trusted publishers".

Certificate Stores

The certificate (ie: the encrypted blob of data) can be stored in a file in
various formats using various different encryption methods, and of course you
could have more than one copy of the same certificate if you want. To be used
with some tool (either for signing code as a software author, or OK'ing
execution of some code as a user), the certificate data needs to be in a "store"
known to the tool, or to the OS.

Of special significance is the store known as the "My" certificate store,
that's unique to each user. Below we'll see where that is and how to view it.

Obtaining and Installing a Certificate

MakeCert or Certificate Vendor?

According to docs, even the least trustworthy certificate from a Certificate
Vendor gives you more capability than a MakeCert certificate.

A MakeCert ("self-signed") certificate is intended to give you capability to
debug on your own machine without being bothered with endless security dialogs.

However, when code is deployed to other users, it appears that self-signed
code triggers a dialog that doesn't give the user an option to "always trust
this publisher", whereas a certificate from a certificate vendor does provide
that benefit. There are doubtless other ramifications for the various levels of
certificate trustworthiness that bear further investigation for larger
deployments.

Below I'll step through obtaining a certificate via each method.

Obtaining a Certificate from MakeCert

1. Find MakeCert.exe. I found it in Visual Studio .NET's set of tools:
\VSNET11\Common7\Tools\Bin
... but it's purportedly available with other products as well, and probably at
MSDN.

2. Run MakeCert. Documentation on MSDN for VBA users suggests the
following command-line (slightly edited for clarity):

This supposedly sets the location of the subject's key
container. However, I couldn't see where this had any impact.

-n "CN=MakeCertTest01"

This provides a name for this publisher's certificate. For
a self-signed certificate, this becomes both the Issued By and
Issued To name.

-b date, -e date

Provides a begin and end date for validity of this key for
signing.

-ss My

Name of the store where this key will be stored. We'll see
below where "My" actually is.

-r

Tells that this is a self-signed certificate.

-eku bunch of numbers
_______________________

A parameter so mysterious that MakeCert's documentation
refers you to C-language header file Wincrypt.h. (It's stuff like this that
gives you a sense of how out-of-step the security business is relative to
the spirit of easy end-user programming fostered by VBA.)

For more documentation on MakeCert.exe, see the table at the end of this
article.

After you've run MakeCert, the new certificate will be available for viewing
using the CertMgr tool, or for use in signing code. More on both these below.

Obtaining a Certificate from a Certificate Vendor

1. Vendors.

There are numerous certificate vendors, which can be located using the
Certificate Authorities link in the table at the bottom of this article. For
this example I have used Verisign.

2. Which Certificate and What Price?

Visiting a Certificate Authority's website often presents you with a
bewildering array of choices. As a software author, you will most likely be
drawn toward a Code Signing Digital Id ("Class 2"), and then be faced with
apparent choices between Microsoft Authenticode, MS Office and VBA Signing
Digital Id, and several others. Then you'll notice the price: several hundred
clams (current exchange rate: 1 clam = US$1).

If you are preparing code for wide deployment, or for retail sale in large
quantity, perhaps this fee is of little consequence, and the level of trust from
this kind of certificate may be entirely worthwhile, perhaps even necessary to
work with corporate security policies. (If so, you also ought to study the
matter in more depth than this introductory article.)

But for those readers who are at earlier or less ambitious stages of
development (though no less important, of course!), perhaps some code for
personal or departmental use, this probably exceeds the lunch-money/petty cash
limit. And this level of trust is probably not needed.

So, we might find ourselves drawn towards one of the cheaper lower-hassle
certificates, such as the low-end "Class 1" certificate, which on VeriSign's
site is referred to as a "Digital ID for Secure E-mail", and costs $14.95 at
this writing. Turns out you can in fact sign code with such a certificate.
Indeed, in a newsgroup exchange a knowledgeable MS staffer described calling
Verisign to verify this fact. And I've actually tried it.

Unfortunately, when code thusly signed is deployed to another machine, the
security warning dialog does not offer to add the publisher to the trusted list.
This is sensible, given that this is not a publisher vetted by anyone
independent. But it also excludes this as a cheap route to signed code.

After much digging, I never was able to find the supposed "Digital ID for
Individual Software Publishers (Class 2) [..] $20 per year", described in MSDN's
"Frequently Asked Questions About Authenticode" (see links at bottom of this
page).

I eventually opted for a $200 Class 2 certificate from Thawte. That's how
dedicated I am :-).

3. Actually Obtaining the Certificate

I'll briefly outline the process so you'll know approximately what you are
getting into.

Step

Discussion

Find correct certificate product on vendor's site.

We want a Class 2 or "code signing" certificate. At time of
writing, for Thawte, start at
www.thawte.com/buy.html and select Code Signing Certificate. This
will bring up pages that detail all the supporting info that you will
eventually need to supply.

Gather supporting docs, and assure yourself that you can
satisfy the requirements

Amongst the info Thawte wants to verify your identify are
included such items as non-free email account, bank account statements (for
address verification, not amount!), business license, articles of
incorporation or "doing-business-as" registrations etc. It may well be
difficult for an individual developer to satisfy the requirements, or for an
employee to satisfy them without cooperation of his/her employer. So check
this out first.

Fill in the web forms providing the basic info

... and complete the credit card payment. Did I mention
it's $200?

Fax in copies of supporting documents

Stand by to be called back.

I was pleased to be called the very next day by a Thawte
representative who asked a few questions to verify that I existed.

Vendor emails details

... on how to have your machine and their server
collaborate to produce a certificate with private key on your machine.

Outcome

The vendor's process may result in a certificate being
"installed" in a store on your PC, or it may result just in one or two file,
such as in Thawte's case, where we end up with .pvk and .spc files.

Preparing Certificate for Use for VBA

Although we now have the certificate (in this case a pair of files) at our
local machine, further steps probably have to be carried out to get the
certificate where we need it for VBA code signing.

The VBA code signing mechanism wants to get certificates from a "store",
probably the My store. Maybe it can use other stores, I didn't investigate. So
we need to read the certificate into the My store. (Note, don't bother with all
of this if using the certificate to sign a DLL -- more on that below.)

Unfortunately, there's apparently a bug in the mechanism which reads
certificates into the My store such that it can't properly consume the pvk/spc
file we got from Thawte. Instead these have to be converted to pfx format which
avoids provoking this bug.

To convert you use the pvkimprt utility, obtainable from MSDN (see links at
bottom of this article). Once you've downloaded and installed that, you would
use a command like:

pvkimprt -pfx CertIJustGot.spc CertIJustGot.pvk

(Of course, depending on the current directory, you may have to provide more
of a path for the files involved). This launches the pvk "import" "wizard"
(though we are not using it for import, but merely to convert from one format to
another). You complete the wizards steps as in the following:

Step

Screenshot

Yes, you want to include the private key part of the
certificate, because that's what allows you to sign code with it.

A password is optional. This causes the code signing
mechanism to always prompt you for a password when applying the signature.
This prevents someone from using your machine to sign something without you
knowing about it.

Provide a name for the output pfx file.

Now that we have certificate data in pfx format we can import it into the My
store using CertMgr tool, which is most readily launched from a menu of Internet
Explorer. (You might wonder why you need to invoke a web browser to install
security features that you use in VBA... but that's the way the Great Powers
have set things up...) So...

Note: The procedure described here is actually a much
shortened version of a Thawte document identified as "Solution Id: vs26211:
Sign a VBA Project with a Microsoft Authenticode Certificate on Windows XP".
It describes a much more convoluted which I an 99% sure achieves the same
result as what I describe here. It is certainly based on what I believe is a
misunderstanding of the function of the pvkimprt tool when used with the
-pfx option. A link to that doc is in the table at end of this
article.

Phew! Now we can collect ourselves and inspect the actual results of this
process....

The Results: Viewing the Installed Certificate

You can view the list of certificates you own
using the CertMgr.exe tool, which is also the tool invoked from within
Internet Explorer: Tools > Internet Options > Content > Certificates >
Personal tab. The screenshot shows what we see after making a MakeCert
certificate, and also obtaining Class 1 and Class 2 (code signing)
certificates.

View > Details

Where Are Certificates Stored? "My" Certificate Store

You may want some corroborative understanding about where certificates are
stored. According to much documentation at MSDN and elsewhere on the web, the My
certificate store is located in the registry, at location:

HKEY_CURRENT_USER\Software\Microsoft\SystemCertificates\My

Most likely, you will find nothing interesting there, leading some to
speculate that this key's contents are somehow hidden. In actuality, it seems
that in recent Microsoft OSes (I'm using Win XP), the My store had been
relocated to the file system, appearing in directory:

...double-click on the Blob field to see which item corresponds to which
trusted publisher.

Actually Signing Code

Oh, that's right, I just remembered what were actually here for... some code
signing :-). OK, with all that preparation taken care of, we can finally sign
some code.

Signing a VBA Project

Assuming you went through the procedure to install the certificate in the My
store as described above...

In the VBA environment, with the project selected, choose
Tools > Digital Signature. This will elicit the dialog shown to the right.
In this case the dialog already offers us a possible certificate to use, but
in case not use the "Choose" button to select from a list of all
certificates stored on this machine for this user.

That's all there is to
it!

If you edit the VBA code later, the signature is automatically reapplied
with no further action needed. As you can surmise from the buttons, you can
later remove the signature, or choose a different one.

Signing a DLL

Signing a DLL, such as a VSL or COM Addin doesn't have to involve the My
store, instead it can work directly with the spc/pvk files. (Apparently you can
also use the My store, but I didn't investigate this.).

To perform the procedure you use the command line signcode tool available
with Visual Studio, and possibly via other channels. Here's an example:

signcode -spc CertIJustGot.spc -v CertIJustGot.pvk MyNewVSL.vsl

(Again, depending on current directory, you may have to provide more
substantial paths to the various files.)

You can type all this in at a command prompt, but since you'll probably want
to sign each new version of the dll/vsl as you compile it, you'll probably
prefer to put this in a batch file or use some other means to tack it onto the
end of your build process.

Roedy Green's Canadian Mind Products site: An eclectic site
with interesting content on subjects from eminently practical, to, uh,
rather delicately personal (so don't browse around too far if easily
offended). It is oddly in keeping with the bizarre world of code signing
lore that it is Roedy who comes up with an outstandingly useful page on code
certs and where to get them.

Commentary

I've left it until last, so you don't have to read my opinion just to get
your code-signing chore on track. But that said, I do have an opinion,
especially if anyone at MS is listening.

Frankly, this code signing business is in a shambles. Virtually every web
document I encountered in this research, produced by the responsible parties (MS
and cert vendors), was either flat wrong, out-of-date or so ambiguous as to lead
to lengthy unnecessary detours. Each of the several sophisticated
developer-level people at MS whom I consulted did not understand what's involved
in this supposedly "simple" code-signing task. Eight months after I reported to
MS the unavailability of $20 code-signing certificates, their most authoritative
document on code signing still claims they exist. Maybe they do, but you sure
can't find them from the certification partners listed by MS.

The security enthusiasts are fond of telling the rest of us that "security
ain't free". OK, fine, I'm prepared for some effort to make things more secure.
But security that is so complicated and or expensive to use that it overloads
solution development efforts to the point of making them impractical, or that
does things like failing silently, is just plain broken as surely as if it was a
bug.

The concept of easy-to-use development environments, especially for "end-user
programming", is to encourage local immediate innovation, and is a means whereby
MS and other vendors present a compelling value proposition to customers. "Look,
your more savvy end-users can automate your local and unique business processes
with Office development tools".

MS is clever about this -- Excel leads to Access leads to SQL Server.
Recording a macro leads to VBA leads to VB (well, it used to), leads to larger
scale apps. Savvy-end-user-ness leads to more rigorous programming ventures
leads to smarter workplaces and smarter people.

That value proposition is thoroughly wiped out if the overhead for the savvy
user to deploy even a one-liner macro to their officemates is dwarfed by a
ridiculous series of hoops, dead-ends and mazes that one must pass through just
to get those %^&* Security Warning dialogs to go away.

And all for what? In theory with code signing an end user can have
confidence that code is from who it purports to be from, and can decline to run
anything suspicious. But if code signing is so difficult, then it just
encourages deployment without it, and in turn encourages users to run with lower
security and to get used to clicking through security warnings from unsigned
code.

Sure, if a user happens to click through a warning that's actually malicious
code, then it will be the user who is most proximally at fault. But that's not
security, it's just blame shifting.