有時(shí)需要讓用戶簽署文本以證明他是完成操作的人。例如,在電子銀行軟件中,用戶可能必須簽署描述交易的文本(“向 IBAN xxxxxxxxx 轉(zhuǎn)賬 300 美元”),或簽署政府電子服務(wù)請求。這可以通過 java-applet 來實(shí)現(xiàn),但由于 JRE 所有者不是大多數(shù),因此最好使用其他方式。
當(dāng)然,前提是用戶有CA簽發(fā)的數(shù)字簽名,并按照CA的手冊在瀏覽器中安裝證書。如果這些步驟沒有成功完成,下面的解決方案將不起作用。
另請注意,這使用 PKCS7(Java 開發(fā)人員:使用充氣城堡來驗(yàn)證它),而不是 XAdES 標(biāo)準(zhǔn)。Internet Explorer 支持 XAdES,但 FireFox 不支持。
讓我們看一個(gè)應(yīng)該對給定文本進(jìn)行簽名的簡單 HTML 頁面:
<script src="sign.js" type="text/javascript"></script>
<input id="text" type="text" />
<input onclick="signDigest(document.getElementById('text').value);" type="button" value="Sign" />
然后是 JavaScript 本身:
function signDigest(text)
{
if(window.event)
window.event.cancelBubble =true;
var dest = sign(text);//TODO
alert(dest);
return dest;
}
// CAPICOM constants
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
var CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_ENCODE_BASE64 = 0;
var CAPICOM_E_CANCELLED = -2138568446;
var CERT_KEY_SPEC_PROP_ID = 6;
function IsCAPICOMInstalled()
{
if(typeof(oCAPICOM) =="object")
{
if( (oCAPICOM.object !=null) )
{
// We found CAPICOM!
return true;
}
}
}
function FindCertificateByHash()
{
try
{
// instantiate the CAPICOM objects
var MyStore =new ActiveXObject("CAPICOM.Store");
// open the current users personal certificate store
MyStore.Open(CAPICOM_CURRENT_USER_STORE,"My", CAPICOM_STORE_OPEN_READ_ONLY);
// find all of the certificates that have the specified hash
var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, strUserCertigicateThumbprint);
var Signer =new ActiveXObject("CAPICOM.Signer");
Signer.Certificate = FilteredCertificates.Item(1);
return Signer;
// Clean Up
MyStore =null;
FilteredCertificates =null;
}
catch (e)
{
if (e.number != CAPICOM_E_CANCELLED)
{
return new ActiveXObject("CAPICOM.Signer");
}
}
}
function sign(src)
{
if(window.crypto && window.crypto.signText)
return sign_NS(src);
return sign_IE(src);
}
function sign_NS(src)
{
var s = crypto.signText(src,"ask" );
return s;
}
function sign_IE(src)
{
try
{
// instantiate the CAPICOM objects
var SignedData =new ActiveXObject("CAPICOM.SignedData");
var TimeAttribute =new ActiveXObject("CAPICOM.Attribute");
// Set the data that we want to sign
SignedData.Content = src;
var Signer = FindCertificateByHash();
// Set the time in which we are applying the signature
var Today =new Date();
TimeAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
TimeAttribute.Value = Today.getVarDate();
Today =null;
Signer.AuthenticatedAttributes.Add(TimeAttribute);
// Do the Sign operation
var szSignature = SignedData.Sign(Signer,true, CAPICOM_ENCODE_BASE64);
return szSignature;
}
catch (e)
{
if (e.number != CAPICOM_E_CANCELLED)
{
alert("An error occurred when attempting to sign the content, the errot was: " + e.description);
}
}
return "";
}
這應(yīng)該可以解決問題,簽名文本可以發(fā)送到服務(wù)器,在那里可以進(jìn)行驗(yàn)證。