Visio 2003 Developer's Survival Pack Notes
|Signing Code: Making Security Warnings Go Away|
|Visio 2003 DSP home This page|
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.
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).
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.
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
App's Security Setting
|Yes||Yes||Operation proceeds||Operation proceeds||Operation proceeds|
|Yes||No||Operation proceeds||App presents warning dialog ||App presents warning dialog |
|No||No||Operation proceeds||App presents warning dialog ||Operation fails, no warning dialog|
| Depending on type of certificate, the
warning dialog may offer the user the option to "always trust software from
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.
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.
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.
... 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".
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.
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.
1. Find MakeCert.exe. I found it in Visual Studio .NET's set of tools:
... 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):
makecert -sk SelfSignedCerts -n "CN=MakeCertTest01" -b 01/01/2003 -e 01/01/2009 -ss My -r -eku 188.8.131.52.184.108.40.206.3
The meaning of the parameters is as follows:
|-sk SelfSignedCerts||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.
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.
|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.|
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:
|Yes, you want to include the private key part of the certificate, because that's what allows you to sign code with it.|
|Disable strong protection. Don't know why... that's just according to Thawte's instructions.|
|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...
IE > Tools > Internet Options > Content > Certificates > Personal tab > Import button, and follow along with the wizard to open the pfx file.
|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:
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:
C:\Documents and Settings\<username>\Application Data\Microsoft\SystemCertificates\My\Certificates
|The individual certificates are stored in individual files, with filenames that correspond to...|
|...the "Thumbprint" field as viewed in in the CertMgr View dialog.|
If you want, you can drop these files into Notepad. They are not exactly text files, but you can get a sense of what's in there.
For what it's worth, other info that you can browse in CertMgr can be found nearby either the registry location or directory location just noted. For example:
|...the list of publishers that you've said you trust (eg: by checking the "always trust this publisher" checkbox on a macro-warning dialog) can be viewed on the Trusted Publishers tab of CertMgr.|
|That list corresponds to a set of keys in the
...double-click on the Blob field to see which item corresponds to which trusted publisher.
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.
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, 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.
|MSDN: Frequently Asked Questions About Authenticode||Frequently Asked Questions About Authenticode|
|MSDN: MakeCert.exe docs||MakeCert|
|MSDN: Certificate Authorities list||Microsoft Root Certificate Program Members|
|VeriSign: Class 1 Cerificates (NOT for code signing)||Digital IDs for Secure E-mail|
|Thawte: select and buy (and also see requirements for) a certificate||thawte buy thawte certificates|
|MSDNL pvkimprt utility||Download details PVK Digital Certificate Files Importer|
|Thawte article on pvkimprt, which I believe is incorrect,
or at least unnecessarily convoluted:
Solution ID: vs26211: Sign a VBA Project with a Microsoft Authenticode Certificate on Windows XP
|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.||Java Glossary: Certificate|
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.
(And if anyone cares to set me straight on something here, please feel free
to email me at:
v11dsp at diagramantics dot com)
Article Created: 2003-11-01 Last edit: Last edit:
Go to: DiagramAntics.com