'************************************************************************* ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ' ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED ' TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A ' PARTICULAR PURPOSE. ' ' Copyright (C) 2001. Microsoft Corporation. All rights reserved. ' ' Modification of "Verify.vbs" CAPICOM 1 sample script to verify either ' included or detached-content CMS/pkcs7 signature data files. ' Signature file can be either binary DER or base64-encoded DER format. ' Can verify content signed as UNICODE-encoded or ASCII-encoded, or ' raw (binary data) byte encoded. ' Can verify content signed with Netscape Formsigning crypto.signText() ' For binary-file usage (ADODB.Stream), requires MDAC 2.5: ' http://support.microsoft.com/default.aspx?scid=kb;EN-US;q231943 ' Uses default Verifyflag: CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE ' ' M. Gallant 07/08/2002 '************************************************************************* ' ' VerifyAll.vbs ' ' This script runs from the command prompt and takes one or two arguments. ' For single argument, assumes that content is included in signature. ' ' 1) filename of a signed/cosigned message to be verified ' 2) filename containing the detached content, required to verify detached signature ' ' Note: For Win95, Win98, WinME, and NT 4.0, this script may sometime ' trigger a known deadlock situation in CRYPT32.DLL, and thus ' not exit completely. ' Please see Q238934 for more information about this problem. ' Option Explicit Const Title = "VerifyAll" Const CAPICOM_LOCAL_MACHINE_STORE = 1 Const CAPICOM_STORE_OPEN_READ_ONLY = 0 Const ForReading = 1, ForWriting = 2 Const ContentFileOut = "contentout.txt" Const CAPICOMdnld = "http://www.microsoft.com/downloads/release.asp?ReleaseID=39546" Dim Verbose :Verbose = FALSE ' Check syntax. If Wscript.Arguments.Count <1 OR Wscript.Arguments.Count > 2 Then MsgBox "Usage: VerifyAll.vbs SignedFileName [ContentFileName] ", _ vbInformation, Title WScript.Quit(1) End If If NOT isCapicomAvailable Then MsgBox "CAPICOM is not installed." & vbCrLf & _ "Install capicom first via: " & vbCrLf & _ CAPICOMdnld, vbCritical, Title WScript.Quit(1) End If '----- Call main signature verification routines -------------- ReDim SignerNames(0) If WScript.Arguments.Count = 1 Then 'Assume we have included-content case DoesFileExist(Wscript.Arguments(0)) VerifyIncludedFile WScript.Arguments(0), ContentFileOut, SignerNames Else 'Assume we have detached-content case DoesFileExist(Wscript.Arguments(0)) DoesFileExist(Wscript.Arguments(1)) VerifyDetachedFile Wscript.Arguments(0), Wscript.Arguments(1), SignerNames End If ' Format signer names. Dim Index Dim Names For Index = 0 to UBound(SignerNames) If Index > 0 Then Names = Names + ", " End If If UBound(SignerNames) > 0 And Index = UBound(SignerNames) Then Names = Names + "and " End If Names = Names + SignerNames(Index) Next Names = Names + "." If WScript.Arguments.Count = 2 Then MsgBox "The signed message of """ & Wscript.Arguments(0) & """ has been " & _ "successfully verified," & vbCrLf & "as a pkcs7 signature file " & _ "using the detached content file """ & _ Wscript.Arguments(1) & """." & vbCrLf & vbCrLf & _ "The message was signed by " & Names, vbInformation, Title Else MsgBox "The signed message of """ & Wscript.Arguments(0) & """ has been " & _ "successfully verified," & vbCrLf & "as a pkcs7 signature file " & _ "using the INCLUDED content " & _ "." & vbCrLf & vbCrLf & _ "The message was signed by " & Names, vbInformation, Title End If Wscript.Quit(0) ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' isCapicomAvailable ' ' Checks if CAPICOM is installed ' Function isCapicomAvailable() Dim oStore On Error Resume Next Set oStore = CreateObject("CAPICOM.Store") oStore.Open CAPICOM_LOCAL_MACHINE_STORE, "Root", CAPICOM_STORE_OPEN_READ_ONLY If Err.Number <> 0 Then isCapicomAvailable = False Exit Function End If isCapicomAvailable = True Set oStore = Nothing On Error GoTo 0 End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' DoesFileExist ' ' Checks if content file to sign exists ' Sub DoesFileExist(FileName) Dim fso Set fso = CreateObject("Scripting.FileSystemObject") If Not fso.FileExists(FileName) Then MsgBox """" & FileName & """ file not found. ", vbCritical, Title WScript.Quit(1) End If Set fso = nothing End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' ErrInfo ' ' Return error number (hex) and information ' Function ErrInfo(Error) ErrInfo = "Error: " & Hex(Error.Number) & " " & Error.Description End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' VerifyIncludedFile ' ' Verify signed message (with included content) of InFile. Try reading InFile ' as text file and if fails, try readint as binary file. ' [Optionally] Save verified content to OutFile, ' and return the list of signer's names to SignerNames. ' Sub VerifyIncludedFile (InFile, OutFile, SignerNames) Dim SignedData, Utils Dim bMessage, Message ' Verify signed message. Set SignedData = CreateObject("CAPICOM.SignedData") LoadFile InFile, Message 'Try loading pkcs7 as text file On Error Resume Next If Verbose Then WScript.Echo "Trying signature file as text file .." End If SignedData.Verify Message, FALSE If Err.Number <> 0 Then ' If error then try reading as binary pkcs7 'WScript.Echo "Reading pkcs7 file as binary ..." If Verbose Then WScript.Echo ErrInfo(Err) & vbCrLf & "Trying signature file as binary .." End If Err.Clear Set Utils = CreateObject("CAPICOM.Utilities") LoadBinFile InFile, bMessage Message = Utils.ByteArrayToBinaryString(bMessage)'convert from byte array to binary-packed string SignedData.Verify Message, FALSE If Err.Number <> 0 Then MsgBox "Could not verify """ & InFile & """ as a pkcs7 signature file with included content. ", _ vbCritical, Title WScript.Quit End If Set Utils = nothing End If On Error GoTo 0 'SaveFile OutFile, SignedData.Content ' Retrieve signer's names. Dim Signer Dim Index : Index = 0 ReDim SignerNames(SignedData.Signers.Count - 1) For Each Signer In SignedData.Signers SignerNames(Index) = Signer.Certificate.GetInfo(0) Index = Index + 1 Next End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' VerifyDetachedFile ' ' Verify detached signed message of InFile using detached content file, ' and return the list of signer's names to SignerNames. ' Sub VerifyDetachedFile (SigFile, ContentFile, SignerNames) Dim SignedData, Utils Dim bMessage, Message Dim bContent, Content ' Verify signed message. Set SignedData = CreateObject("CAPICOM.SignedData") '----- First try reading pkcs7 and content files as text ---- 'Load signature from SigFile to Message buffer 'Load message text from ContentFile to Content buffer LoadFile SigFile, Message LoadFile ContentFile, Content On Error Resume Next If Verbose Then WScript.Echo "Trying UNICODE byte-encoding .." End If SignedData.Content = Content ' Try default vbs UNICODE string SignedData.Verify Message, TRUE ' Detached signature If Err.Number <> 0 Then ' If error, see if data signed was ASCII byte-encoded If Verbose Then WScript.Echo ErrInfo(Err) & vbCrLf & "Trying ASCII byte-encoding .." End If Err.Clear SignedData.Content = MyStrConv(Content) 'UNICODE to ASCII string SignedData.Verify Message, TRUE ' Try verifying ASCII byte-encoded signature '---- If fails, try reading pkcs7 and content as binary files ---- If Err.Number <> 0 Then If Verbose Then WScript.Echo ErrInfo(Err) & vbCrLf & "Trying reading as binary files ..." End If Err.Clear Set Utils = CreateObject("CAPICOM.Utilities") LoadBinFile SigFile, bMessage LoadBinFile ContentFile, bContent Message = Utils.ByteArrayToBinaryString(bMessage)'byte array to binary-packed string Content = Utils.ByteArrayToBinaryString(bContent) SignedData.Content = Content SignedData.Verify Message, TRUE If Err.Number <> 0 Then If Verbose Then WScript.Echo ErrInfo(Err) & vbCrLf & "Signature Verification failed!" End If MsgBox "Could not verify """ & SigFile & _ """ as a pkcs7 signature file " & vbCrLf & _ "with detached content file """ & ContentFile & """. ", _ vbCritical, Title WScript.Quit End If Set Utils = nothing End If End If On Error Goto 0 ' Retrieve signer's names. Dim Signer Dim Index : Index = 0 ReDim SignerNames(SignedData.Signers.Count - 1) For Each Signer In SignedData.Signers SignerNames(Index) = Signer.Certificate.GetInfo(0) Index = Index + 1 Next End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' LoadFile ' ' Read content of FileName and assign to Buffer as string. ' Sub LoadFile (FileName, Buffer) Dim fso Set fso = CreateObject("Scripting.FileSystemObject") If Not fso.FileExists(FileName) Then MsgBox "Error: " & FileName & " file not found." Exit Sub End If Dim ts Set ts = fso.OpenTextFile(FileName, ForReading) Buffer = ts.ReadAll End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' LoadBinFile ' ' Read content of FileName and return as byte array. ' Sub LoadBinFile (FileName, bBuffer) Const adReadAll = -1 Dim oStream, bFileData Set oStream = WScript.CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 ' adTypeBinary oStream.LoadFromFile FileName bBuffer = oStream.Read(adReadAll) oStream.Close Set oStream = nothing End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' SaveFile ' ' Save string Buffer to FileName. ' Sub SaveFile (FileName, Buffer) Dim fso Set fso = CreateObject("Scripting.FileSystemObject") Dim ts Set ts = fso.OpenTextFile(FileName, ForWriting, True) ts.Write Buffer End Sub ' --- Convert from UNICODE string to ASCII byte buffer -------- Function MyStrConv(Ustr) Dim i Dim ch MyStrConv = "" For i = 1 to Len(Ustr) ch = Mid(Ustr, i, 1) MyStrConv = MyStrConv & ChrB(AscB(ch)) Next End Function