App下載

如何僅使用 Javascript 創(chuàng)建數(shù)字簽名解決方案

杯酒挽歌 2021-09-22 16:52:43 瀏覽數(shù) (2467)
反饋

有時(shí)需要讓用戶簽署文本以證明他是完成操作的人。例如,在電子銀行軟件中,用戶可能必須簽署描述交易的文本(“向 IBAN xxxxxxxxx 轉(zhuǎn)賬 300 美元”),或簽署政府電子服務(wù)請(qǐng)求。這可以通過(guò) java-applet 來(lái)實(shí)現(xiàn),但由于 JRE 所有者不是大多數(shù),因此最好使用其他方式。

當(dāng)然,前提是用戶有CA簽發(fā)的數(shù)字簽名,并按照CA的手冊(cè)在瀏覽器中安裝證書(shū)。如果這些步驟沒(méi)有成功完成,下面的解決方案將不起作用。

另請(qǐng)注意,這使用 PKCS7(Java 開(kāi)發(fā)人員:使用充氣城堡來(lái)驗(yàn)證它),而不是 XAdES 標(biāo)準(zhǔn)。Internet Explorer 支持 XAdES,但 FireFox 不支持。

讓我們看一個(gè)應(yīng)該對(duì)給定文本進(jìn)行簽名的簡(jiǎn)單 HTML 頁(yè)面:

<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 &amp;&amp; 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)該可以解決問(wèn)題,簽名文本可以發(fā)送到服務(wù)器,在那里可以進(jìn)行驗(yàn)證。


0 人點(diǎn)贊