白話數字簽名 3Web程式中的數字簽名

2022-11-19 23:54:05 字數 4927 閱讀 2802

摘要閱讀本文並探索

- 如何突破web程式無狀態性這個讓人抓狂的障礙實現自動顯示簽名結果和批量簽名功能。

- 如何將簽名功能封裝到乙個實現了ihttphandler介面的類庫中,使client端的**盡可能的簡單。

- 使用數字簽名api函式需要注意的幾個問題。

本文介紹在web程式中使用數字簽名所遇到的特殊困難和解決方法,並給出乙個超簡單但相當實用的demo。

demo程式的效果

讓我們先來看看實現之後的效果。

讓client端**盡可能的簡單

我們將數字簽名操作的複雜性全部封裝到乙個命名空間為的類庫中,類庫只暴露乙個名為signer的類。

signer的client (本例中的的職責只有

- 構造乙個含有待簽名的資料的dictionary作為signer的輸入,然後呼叫函式進行數字簽名。

- 在頁面上放置乙個專門用於取得並顯示簽名結果的按鈕,並將這個按鈕的clientid傳遞給signer,這樣signer在完成簽名後就可以自動觸發這個按鈕。在將程式發布給終端使用者時,要把這個按鈕的top屬性設為-10000,這樣終端使用者就看不到這個按鈕了。

的設計檢視的截圖

的源**如下

由於signer是乙個http 處理程式,所以需要在中新增一行對的註冊:

有關http處理程式的建立和應用,可以看《實戰 http 處理程式(http handler)系列》。

由於我們把複雜性都放在了中,的**有些長,我們會在後面討論它的幾個要點。

的第227和228行的「和「我把它們放在了類庫的配置檔案裡,它們的**如下:

自動顯示簽名結果

我們想要實現這樣的互動效果:使用者選定想要進行簽名的資料後,只要按乙個按鈕就會自動彈出乙個小窗體顯示簽名的進度;當簽名結束後,可以自動顯示簽名結果,就像上面那個demo程式所展示的那樣。

如果我們開發的是winform的資訊系統,實現這樣的效果簡直易如反掌。可是在web程式中,我們卻遇到了一點麻煩。

自動顯示簽名結果的困難

正如我們在第2篇所介紹的,為了防複製破解,我們是使用usb key做數字簽名。這個usb key必須插在客戶端的電腦上,我們在server端無法直接控制它, key進行簽名,再將簽名結果通過hiddenfields post回server端——不過這個server端已經不是以前的server端了,web程式的這種無狀態性沒少讓我們吃虧。

換句話說,我們沒辦法像下面這樣寫(偽碼):

protected void do_sign_button_click(object sender, eventargs e)

實現自動顯示簽名結果

我們遇到的問題的實質是:準備簽名資料(偽**第1行)、顯示簽名結果(偽**第3、4行)的操作在server端進行;而使用usb key進行簽名的操作(偽**第2行)必須在client端的瀏覽器上執行,並且這兩種操作是非同步的!所以我們只能將顯示簽名結果的**放到另乙個函式中,在簽名結束後以某種方法觸發它。

我們在demo中所使用的方法是,將顯示簽名結果的**放到「顯示簽名結果(自動)」按鈕的click事件中,在簽名結束後,使用

來觸發這個按鈕的click事件。

思考題我們使用乙個「偽隱藏」的按鈕可以簡單地實現自動顯示簽名結果的效果,不過這種作法似乎有點土。你能否使用其它更「高階」的方法來實現同樣的效果?

實現批量簽名

我們需要讓使用者按一次按鈕,就可以簽名 n 條資料,可是數字簽名api signdataex(sourcedata,...) 一次只能簽名一條資料。我們需要遍歷每條待簽名資料,呼叫signdataex()進行簽名。

我們有兩種選擇:

1. 在server端進行遍歷,每次傳送一條資料給client端進行簽名。

2. 將 n 條待簽名資料一次全部傳給client端,在client端使用j**ascript的for迴圈遍歷待簽名資料並進行簽名。

我們在demo程式中是使用了第1種方法。基於和「自動顯示簽名結果」一節所述的同樣的困難,我們無法在的processrequest()中這樣寫(偽碼):

public void processrequest( context)

}好在已經有大師發明了外部迭代器(external iterator),我們可以在第一次迭代之前,先建立乙個待簽名資料的乙個外部迭代器,並把它儲存在session中。每次簽名後,client端postback回server端,在server端從session中取出這個外部迭代器,呼叫sign_candidates_之後繼續向client端傳送簽名用的j**ascript語句,直至完成全部遍歷,請參見的250~268行。下面的時序圖表示批量簽名3條資料的過程。

思考題我們的demo實現了第1種方法,你能否實現第2種方法?這兩種實現方法各有什麼優缺點?

綜合起來

我們把批量簽名與自動顯示簽名結果的功能都放在中,可以用下面這個經過簡化的時序圖來表示。

附錄數字簽名api簡介

我們使用的是遼寧省數字認證中心發放的數字證書。他們還提供了兩套數字簽名api:乙個是activex控制項;乙個是com元件。

兩套api都有完整、豐富的數字簽名相關的函式,可以單獨使用。如果是winform程式,直接使用com元件即可。不過由於web程式必須使用activex控制項,所以我們在作數字簽名的時候使用activex控制項,在驗證簽名的時候使用com元件。

也許您手頭的api和我們使用的api並不相同,不過您仍然可以**這兩套api的手冊找找感覺。

lncatoolkits 控制項(通用版)程式設計師手冊_ <- 這個是activex控制項的手冊

lnca-cryptoapi-com版程式設計師手冊_ <- 這個是com元件的手冊

作數字簽名的api函式是signdataex()。

函式宣告: bstr signdataex (bstr szsrc,

bstr ssignalgo,

long isaddsigncert,

long isaddsrcdata,

bstr szinneroid,

long isaddtime,

bstr ppin);

說明:進行簽名資料操作(使用客戶端證書)。

引數:.. szsrc :原文資料

.. ssignalgo:指定簽名演算法

szoid_oiwsec_sha1 = 「1.3.14.3.2.26」

szoid_rsa_md5 = 「1.2.840.113549.2.5」

szoid_rsa_md2 = 「1.2.840.113549.2.2」

.. isaddsigncert 是否在結果中攜帶證書

0 = 不攜帶證書

1 = 攜帶證書

.. isaddsrcdata 是否在結果中攜帶原文

0 = 不攜帶原文

1 = 攜帶原文

.. szinneroid:資料型別oid,(預設:null)

szoid_tsp_tstinfo = "1.2.840.113549.1.9.16.1.4"

.. isaddtime:是否新增簽名時間

0: 不進行時間編碼

1: 取當前系統時間,進行時間編碼

2、從時間戳伺服器取得時間,必須首先設定時間戳伺服器url。請參考7.14

章節的時間戳操作。

.. ppin:使用者key 口令

如果輸入正確的口令,則不彈出輸入口令視窗,直接簽名資料。

如果輸入錯誤的口令,則彈出輸入口令視窗

其中:通過inputdatatype 屬性來指定原文資料格式

0 = 輸入原文為二進位制編碼,此函式內部不進行轉碼

1 = 輸入原文為base64 編碼,此函式內部進行轉碼

返回值:成功時返回簽名資料(base64 編碼),

失敗時返回空,由errorcode 屬性中取錯誤碼,由errormessage 屬性中取錯誤信

息。需要說明的是isaddsigncert這個引數。它指示是否在簽名資料中攜帶證書。

攜帶證書的優點:如果選擇攜帶證書,在驗證簽名時就不用再向驗證簽名的函式顯式傳遞乙個證書。驗證簽名的函式會自動從簽名資料中解析出證書,然後驗證簽名,這在程式設計上無疑是非常方便的!

如果選擇不攜帶證書,我們就必須將系統所有使用者的證書儲存在乙個「證書表」中,再在含有簽名資料字段的表中建立乙個專門儲存「證書表」id的字段,在驗證簽名前要從「證書表」中取得證書,再驗證簽名。

攜帶證書的缺點:缺點是會使簽名資料比較長,例如對「1234」簽名的base64編碼會有1942個字元;而如果不攜帶證書只有560個字元。所以如果客戶十分吝嗇資料庫的儲存空間,就需要使用不攜帶證書的方式。

不過我個人是十分喜歡攜帶證書的方式的(偶是懶人^_^)

還有就是isaddsrcdata這個引數應該指定為「攜帶原文」,這樣在驗證簽名的時候(使用com元件的verifysign函式)就不用再給出原文了(sourcedata引數設為null),而且verifysign()函式在驗證成功後會返回原文,這樣還可以向使用者顯示這樣的資訊:「看,以前簽名的是這個資料(verifysign()函式返回的原文),現在被改成了這個資料(表中原文字段中的值),所以驗證失敗」。

本篇源****

本篇源**。執行本篇的demo需要預先安裝簽名用的activex控制項:activex_bin_v2.

8.6.0_解壓縮後執行reg_即可完成安裝,還有你的 usb key要支援這個activex控制項才行。

致謝非常感謝遼寧省數字認證中心軟體開發部專案經理張鐵夫先生的指導和幫助。每次**諮詢都能得到他的耐心講解,即使我們已經試用了半年多仍然沒有購買乙個數字證書^_^

感謝一直關注本系列的各位同仁,大家的鼓勵和指導令我受益匪淺。感謝古巴、clark zheng、菜菜灰在http 處理程式方面對我的指導。感謝笑望人生、蛙蛙池塘、大石頭、aspnetx、銀河、慢一拍、遊民一族、yoyolion對本系列的補充和指正。

工具箱本系列的所有流程圖均使用visio2003繪製。

uml 時序圖使用di**0.96.1繪製。

抓圖軟體使用的是snigitv7.1.1。**上使用了手寫字型方正靜蕾簡體。

**預覽和格式轉換使用了acdseev5.0。

文字部分使用google 拼音輸入法鍵入。

從數字簽名的工作原理看電子商務安全

pdf 中心 page 1 of 3 從數字簽名的工作原理看電子商務安全 數字簽名已成為資訊社會中人們保障網路身份安全的重要手段之一,然而,隨著安全威脅的日益猖獗,數字簽名還能給企業和消費者帶來安全嗎?世界各地制訂了賦予數字簽名合法地位的法律。一些人認為,這些法律對電子商務和 金融服務公司而言無疑是...

淘氣的數字「3」

自然數家族中最調皮的要算數3了。由於他個頭長得比較矮,大家都親切地叫他 小3 小3 走路不都不好好走。他走起路來連躥帶蹦,餓時身體往前走眼睛卻往後瞧。這一次,小3又歪著腦袋一溜煙地往前跑,咚 的一聲和一位白鬍子老爺爺撞了個滿懷。白鬍子老爺爺於 小3 你又到處亂跑,撞了車碰了人多不好。小3 不以為然地...

PMP 3 大白話PMP之 什麼是專案管理

3 大白話pmp之 什麼是專案管理?純屬個人觀點,僅用於娛樂 前面兩篇 了兩個問題,1,什麼是專案。2,專案成果。接下來說一說,什麼是專案管理,以及專案管理管什麼。先引用教科書的語言,看看專案管理的定義 專案管理 百科 專案管理是乙個管理學分支的學科 指在專案活動中運用專門的知識 技能 工具和方法,...