有史以來(lái)第一次您可以敲打一下計(jì)算機(jī)并得到有意義的響應(yīng)!使用 Linux® 和 Hard Drive Active Protection System(硬盤(pán)活動(dòng)保護(hù)系統(tǒng)HDAPS)內(nèi)核驅(qū)動(dòng)程序我們可以訪問(wèn) Lenovo(以前稱為 IBM®)ThinkPads 上的嵌入式加速器然后處理加速器的數(shù)據(jù)來(lái)讀取特定 敲打 事件序列(也就是您使用關(guān)節(jié)敲打筆記本的事件序列)并基于這些敲打事件運(yùn)行一些命令雙擊鎖定屏幕然后敲入密碼來(lái)解鎖敲打顯示屏一次就可以讓 MP 播放器前進(jìn)一個(gè)音軌這類可能事物是無(wú)窮無(wú)盡的
年IBM 開(kāi)始發(fā)行集成了加速器和相關(guān)軟件的 ThinkPad 筆記本以便在筆記本掉到地上時(shí)對(duì)硬盤(pán)進(jìn)行保護(hù)來(lái)自 IBM 和其他地方的黑客已經(jīng)為 Linux 內(nèi)核開(kāi)發(fā)了一些模塊來(lái)利用這些傳感器的優(yōu)點(diǎn)屏幕顯示方向桌面切換甚至是游戲控制和實(shí)時(shí)的筆記本傾斜度 D 模塊現(xiàn)在都已經(jīng)可以使用了本文將展示 敲打代碼 這種新技術(shù)和一個(gè)簡(jiǎn)單程序該程序在檢測(cè)到特定的敲打代碼時(shí)會(huì)運(yùn)行一些命令
使用帶有 HDAPS 驅(qū)動(dòng)的已更新的內(nèi)核我們就可以用一個(gè)簡(jiǎn)單程序 knockAge 來(lái)生成敲打代碼了我們也可以下載并使用一個(gè) Perl 腳本來(lái)定制自己的敲打輸入環(huán)境請(qǐng)參閱本文最后的 下載 和 參考資料 部分給出的鏈接其中包括了解 knockAge 操作的鏈接
硬件需求
容易實(shí)現(xiàn)
正如您從展示視頻(請(qǐng)參見(jiàn)下面 參考資料 中的鏈接)可以看到的敲打操作是由一系列指節(jié)敲打構(gòu)成的盡管 ThinkPad 的加速器是為保護(hù)它不受意外事件的影響但太強(qiáng)力的振蕩仍然會(huì)對(duì)硬盤(pán)造成損壞因此我們必須小心
很多在 年以及這以后生產(chǎn)的 IBM(現(xiàn)在是 Lenovo)的 ThinkPads 中都有 HDAPS 硬件如果您不確定自己的硬件配置可以檢查 Lenovo 的 Web 站點(diǎn)上關(guān)于您自己型號(hào)的機(jī)器的技術(shù)細(xì)節(jié)如果您的機(jī)器上沒(méi)有 ThinkPad那么這段代碼可能無(wú)法在您的筆記本上正常工作
本文是在 x 體系架構(gòu)上編寫(xiě)的本文中的代碼是在 ThinkPad Tp 的兩個(gè)不同模塊上進(jìn)行開(kāi)發(fā)和測(cè)試的有關(guān) ThinkPad 硬件的鏈接請(qǐng)參閱 參考資料 部分
如果您有一臺(tái) Apple MacBook那么您可能也有這種加速器并且可以使用相同的方法通過(guò)內(nèi)核訪問(wèn)它們?nèi)欢疚闹械拇a并沒(méi)有在 Apple 硬件上進(jìn)行測(cè)試
軟件要求
HDAPS 驅(qū)動(dòng)程序必須包括在內(nèi)核中才能啟用對(duì)加速器的訪問(wèn)試圖對(duì)現(xiàn)有內(nèi)核增加補(bǔ)丁也不會(huì)獲得成功因此我們建議從自己喜歡的鏡像站點(diǎn)上下載最新的內(nèi)核新內(nèi)核發(fā)行版中已經(jīng)包含了對(duì) HDAPS 驅(qū)動(dòng)程序的支持
啟動(dòng)內(nèi)核配置選擇程序并在配置中包含 HDAPS 驅(qū)動(dòng)程序HDAPS 驅(qū)動(dòng)程序位于Device Drivers > Hardware Monitoring Support > IBM Hard Drive Active Protection System (hdaps) 選項(xiàng)中更多的內(nèi)核配置和安裝過(guò)程已經(jīng)超出了本文的范圍但是在 Web 站點(diǎn)上有很多教程可以提供具體的幫助有關(guān)可以幫助我們?nèi)腴T(mén)的鏈接請(qǐng)參閱 參考資料 一節(jié)的內(nèi)容
本文是在 版本的內(nèi)核上進(jìn)行開(kāi)發(fā)和測(cè)試的
創(chuàng)建簡(jiǎn)單的敲打序列
從 下載 一節(jié)的鏈接中下載源代碼并從中找到 knockAgepl 腳本這就是讓我們可以創(chuàng)建敲打序列的主要 Perl 程序它還允許監(jiān)聽(tīng)特殊的敲打序列并運(yùn)行命令下面讓我們來(lái)介紹一下這個(gè)用戶空間程序的用法以及 knockAgepl 程序的配置然后再對(duì)這個(gè)函數(shù)進(jìn)行回顧
使用下面的命令運(yùn)行 knockAgepl 程序
perl knockAgepl c
這會(huì)啟動(dòng) Perl 程序來(lái)監(jiān)聽(tīng)敲打事件并記錄下它們之間的間距以供將來(lái)使用一旦程序開(kāi)始運(yùn)行之后對(duì)筆記本進(jìn)行的敲打操作就會(huì)產(chǎn)生效果我們并不需要在物理上移動(dòng)自己的 ThinkPad 來(lái)注冊(cè)敲打事件如果 ThinkPad 在一個(gè)平面上只要對(duì)其進(jìn)行一些移動(dòng)和滑行即可我建議您用左右握住 ThinkPad 左邊接近連接軸的地方同時(shí)用右手在距離 LCD 底部 英寸的地方敲打顯示屏即可請(qǐng)參閱 下載 部分給出的視頻展示或參閱 參考資料 中用來(lái)創(chuàng)建敲打序列的例子
體驗(yàn)不同的敲打幅度和力度從而了解 knockAge 程序能夠捕獲的事件判斷率對(duì)于創(chuàng)建復(fù)雜的敲打事件來(lái)說(shuō)這非常重要
第一次真正嘗試敲打應(yīng)該非常簡(jiǎn)單兩次雙擊之間停留 秒然后再次運(yùn)行 perl knockAgepl c在看到 enter a knock sequence 時(shí)穩(wěn)定地敲打 LCD 邊上兩次中間停留 秒在 秒之后會(huì)自動(dòng)超時(shí)(這是可以配置的)您所敲打的序列會(huì)被打印出來(lái)這類似于下面的例子
_#_ (command here) _#_
讓我們來(lái)分析一下這一行的內(nèi)容敲打序列分隔符命令區(qū)分隔符最后是注釋區(qū)我們的下一個(gè)步驟是將這行內(nèi)容復(fù)制到 knockAgepl 程序使用的默認(rèn)配置文件 {$HOME}/knockFile 中該配置文件也可能是 /home//knockFile 文件在使用上面的敲打序列行創(chuàng)建好 knockFile 文件之后就可以對(duì)這行進(jìn)行修改來(lái)運(yùn)行程序了將 (command here) 文本修改成 /bin/echo double tap并將注釋區(qū)的內(nèi)容修改成更有意義的內(nèi)容例如
_#_ /bin/echo double tap _#_ Double tap event
現(xiàn)在我們已經(jīng)修改好這個(gè)配置文件可以打印一條通知了接下來(lái)使用下面的命令在守護(hù)模式下運(yùn)行 knockAge 腳本
perl knockAgepl
這個(gè)程序會(huì)在后臺(tái)安靜地監(jiān)聽(tīng) ~/knockFile 所羅列的事件請(qǐng)使用相同的間隔再次雙擊屏幕您會(huì)看到在屏幕上打印出了 double tap 消息如果我們希望更詳細(xì)地了解 knockAgepl 腳本是如何工作的那么我們可以使用下面的命令在守護(hù)模式下運(yùn)行它
perl knockAgepl v
使用 xscreensaver 鎖定屏幕或打開(kāi)屏幕
創(chuàng)建 password 序列
使用下面的命令在 create 模式下運(yùn)行 knockAgepl 程序
perl knockAgepl c
現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)解鎖的密碼序列我建議使用 刮臉和理發(fā)的動(dòng)作請(qǐng)確保每次您都可以以一貫精確的方式執(zhí)行這個(gè)動(dòng)作盡管您可以通過(guò)修改參數(shù)來(lái)控制輸入密碼敲打操作所需要的精度但是這仍然很難匹配精確的時(shí)間刮臉和理發(fā)動(dòng)作 除了可以提供穩(wěn)定的擊打順序之外其復(fù)雜性和簡(jiǎn)單性對(duì)于屏保解鎖密碼來(lái)說(shuō)也非常適合下面是一個(gè)刮臉和理發(fā)動(dòng)作 的擊打序列示例
_#_ /bin/echo shave the haircut _#_ two bits
在進(jìn)行下一步操作之前您應(yīng)該體驗(yàn)一下上面的命令和 ~/knockFile 配置文件中的雙擊命令這可以在屏保運(yùn)行時(shí)提供很好的幫助它更難檢測(cè)出敲打是否正確[!--empirenews.page--]
xscreensaver 所使用的命令配置
以下設(shè)置假設(shè)您已經(jīng)登錄到了窗口管理器中并且已經(jīng)使用您的 userid 啟動(dòng)了xscreensaver 程序例如如果您正在運(yùn)行 Fedora Core 并且使用 gdm 登錄到 KDE 中那么 xscreensaver 就會(huì)自動(dòng)啟動(dòng)因此要激活它則需要將雙擊命令從
/bin/echo double tap
修改為
xscreensavercommand activate &
現(xiàn)在每次識(shí)別出有 雙擊 事件發(fā)生時(shí)xscreensaver 程序都會(huì)使用所指定的內(nèi)容來(lái)激活一旦 screensaver 被激活就可以通過(guò)輸入密碼(如果是這樣配置的)對(duì)屏幕進(jìn)行解鎖不過(guò)我們真正希望的是自己的朋友也可以使用密碼解鎖代碼來(lái)解除屏保因此我們需要在 ~/knockFile 文件中將下面的命令
/bin/echo shave the haircut
替換為
killall xscreensaver ; nohup xscreensaver nosplash >/dev/null >/dev/null &
這個(gè)命令會(huì)停止當(dāng)前運(yùn)行的所有 xscreensaver 程序然后在后臺(tái)再重新啟動(dòng) xscreensaver現(xiàn)在我們可以通過(guò)敲打屏幕邊來(lái)重復(fù)加鎖和解鎖計(jì)算機(jī)屏保的過(guò)程這比藍(lán)牙提供的近似度加鎖更加安全或更方便嗎?答案可能是否定的它更酷嗎?當(dāng)然!
更多例子
HDAPS 傳感器和 knockAgepl 程序提供了另外一種用戶輸入設(shè)備我們可以使用它們以獨(dú)特的方式進(jìn)行輸入例如
如果計(jì)劃在一個(gè)基礎(chǔ)上測(cè)試新的 X 配置文件可以將雙擊條目更改為重新啟動(dòng)配置好的 X 服務(wù)器這樣就不需要敲任何其他鍵來(lái)強(qiáng)制重啟了
在命令區(qū)中可以放上我們喜歡使用的任何 shell 腳本這樣就可以使用雙擊來(lái)查看 email
以最新的組合節(jié)拍進(jìn)行敲打讓 ThinkLight 顯示 WWII 代在 Kinakuta 的黃金存儲(chǔ)設(shè)備的 Morse 密碼位置
敲入 Morse 編碼防止鍵盤(pán)輸入被記錄
請(qǐng)參閱 參考資料 部分給出的有關(guān)將 ThinkPad 的傾斜度用于游戲顯示工具的例子或者直接跳過(guò)這部分內(nèi)容將 Threshold 變量設(shè)置為 這樣您使勁踢一腳 ThinkPad它就會(huì)自動(dòng)重啟了
knockAgepl 代碼
歷史和策略
Jeff Molofee 所編寫(xiě)的 hdapsglc 是 knockAgepl 代碼的基礎(chǔ)Hdapsglc 是一個(gè)非常好的展示程序可以展示如何使用傾斜傳感器來(lái)實(shí)時(shí)地顯示有關(guān) ThinkPad 的方向的信息二者之間的區(qū)別是本例將時(shí)間上隔離的事件組織在一起創(chuàng)建了敲打事件同時(shí)提供了相關(guān)的代碼來(lái)創(chuàng)建并監(jiān)聽(tīng)敲打事件序列
參數(shù)配置
下面讓我們來(lái)使用對(duì)時(shí)間和傳感器敏感的一些參數(shù)來(lái)啟動(dòng) knockAgepl
清單 主程序參數(shù)
require sys/syscallph; # for subsecond timing my $option = $ARGV[] || ; # simple option handling # filename for hdaps sensor reads my $hdapsFN = /sys/devices/platform/hdaps/position; my $UPDATE_THRESHOLD = ; # threshold of force that indicates a knock my $INTERVAL_THRESHOLD = ; # microseconds of time required between knock # events my $SLEEP_INTERVAL = ; # time to pause between hdaps reads my $MAX_TIMEOUT_LENGTH = ; # maximum length in seconds of knock pattern # length my $MAX_KNOCK_DEV = ; # maximum acceptable deviation between recorded # pattern values and knocking values my $LISTEN_TIMEOUT = ; # timeout value in seconds between knock # events when in listening mode
這些變量及其注釋都非常簡(jiǎn)單它們的用法和配置選項(xiàng)在本文后面部分會(huì)進(jìn)行解釋下面是其余的一些全局變量及其描述
清單 敲打模式參數(shù)
my @baseKnocks = (); # contains knock intervals currently entered my %knockHash = (); # contains knock patterns associated commands my $prevInterval = ; # previous interval of time my $knockCount = ; # current number of knocks detected my $restX = ; # `resting positiong of X axis accelerometer my $restY = ; # `resting positiong of Y axis accelerometer my $currX = ; # current position of X axis accelerometer my $currY = ; # current position of Y axis accelerometer my $lastX = ; # most recent position of X axis accelerometer my $lastY = ; # most recent position of Y axis accelerometer my $startTime = ; # to manage timeout intervals my $currTime = ; # to manage timeout intervals my $timeOut = ; # perpetual loop variable my $knockAge = ; # count of knocks to cycle time interval
子程序
在我們的子程序清單中首先是一個(gè)簡(jiǎn)單的邏輯塊用來(lái)檢查是否有加速器可讀
清單 檢查加速器的子程序
sub checkAccelerometer() { my $ret; $ret = readPosition (); if( $ret ){ print no accelerometer data available tis bork edn; exit(); } }#checkAccelerometer
Jeff Molofee 編寫(xiě)的 hdapsglc 代碼為 knockAgepl 中的所有代碼提供了一個(gè)很好的起點(diǎn)在下面的 readPosition 子程序中我們可以看到他的注釋這個(gè)子程序?qū)⒋蜷_(kāi)一個(gè)文件從中讀取當(dāng)前的加速器數(shù)據(jù)然后關(guān)閉文件并返回不包含 (逗號(hào)) 字符的數(shù)據(jù)
清單 readPosition subroutine
## comments from Jeff Molofee in hdapsglc #* read_position read the (xy) position pair from hdaps #* #* We open and close the file on every invocation which is lame but due to #* several features of sysfs files: #* #* (a) Sysfs files are seekable #* (b) Seeking to zero and then rereading does not seem to work ## sub readPosition() { my ($posX $posY) = ; my $fd = open(FH $hdapsFN); while( ){ s/(//g; s/)//g; ($posX $posY) = split ; }# while read close(FH); return( $posX $posY ); }#readPosition
getEpochSeconds 和 getEpochMicroSeconds 提供了有關(guān)敲打模式狀態(tài)的詳細(xì)而精確的信息
清單 時(shí)間分隔器
sub getEpochMicroSeconds { my $TIMEVAL_T = LL; # LL for microseconds my $timeVal = pack($TIMEVAL_T ()); syscall(&SYS_gettimeofday $timeVal ) != or die micro seconds: $!; my @vals = unpack( $TIMEVAL_T $timeVal ); $timeVal = $vals[] $vals[]; $timeVal = substr( $timeVal ); my $padLen = length($timeVal); $timeVal = $timeVal x $padLen; return($timeVal); }#getEpochMicroSeconds sub getEpochSeconds { my $TIMEVAL_T = LL; # LL for microseconds my $start = pack($TIMEVAL_T ()); syscall(&SYS_gettimeofday$start ) != or die seconds: $!; return( (unpack($TIMEVAL_T $start))[] ); }#getEpochSeconds[!--empirenews.page--]
接下來(lái)是 knockListen 子程序前 行負(fù)責(zé)讀取當(dāng)前的加速器數(shù)據(jù)值并對(duì)基本的值讀取進(jìn)行調(diào)整如果加速器的數(shù)量在某一維度上大于更新上限值那么 checkKnock 變量就被設(shè)置為 為了調(diào)整這個(gè)程序使它只響應(yīng)我們需要的敲打事件或類似的加速值我們需要擴(kuò)大更新上限例如我們可以將 ThinkPad 放到自己的汽車中并讓它在檢測(cè)到硬加速(或減速)時(shí)更改 MP 播放列表
如果敲打筆記本的力度足夠大并且大于了更新上限那么就會(huì)導(dǎo)致調(diào)用getEpochMicroSeconds 子程序然后 diffInterval 變量會(huì)在兩次敲打事件之間被賦值這個(gè)值將很多擊打力度大于更新上限的很多快速加速讀取壓縮到一個(gè)時(shí)間中如果沒(méi)有間隔上限檢查一次硬敲打就會(huì)被注冊(cè)成很多事件就仿佛是加速器連續(xù)一段時(shí)間產(chǎn)生大量事件一樣這種行為對(duì)于用戶的視力和觸覺(jué)來(lái)說(shuō)都是無(wú)法感知到的但對(duì)于 HDAPS 來(lái)說(shuō)顯然并非如此如果已經(jīng)達(dá)到了間隔上限那么敲打間隔會(huì)被記錄在 baseKnocks 數(shù)組中然后將兩次敲打之間的間隔重置
仔細(xì)修改這些變量可以幫助對(duì)程序進(jìn)行優(yōu)化從而識(shí)別出您特有的敲打風(fēng)格縮小更新上限并擴(kuò)大周期上限可以檢測(cè)出更多間隔的輕微敲打機(jī)械敲打設(shè)備或特定的敲打方法可能會(huì)需要降低間隔上限從而識(shí)別出獨(dú)特的敲打事件
清單 knockListen 子程序
sub knockListen() { my $checkKnock = ; ($currX $currY) = readPosition(); $currX = $restX; # adjust for rest data state $currY = $restY; # adjust for rest data state # require a high threshold of acceleration to ignore nonevents like # bashing the enter key or hitting the side with the mouse if( abs ($currX) > $UPDATE_THRESHOLD) { $checkKnock = ; } if( abs ($currY) > $UPDATE_THRESHOLD) { $checkKnock = ; } if( $checkKnock == ){ my $currVal = getEpochMicroSeconds(); my $diffInterval = abs($prevInterval $currVal); # hard knock events can create continuous acceleration across a large time # threshold requiring an elapsed time between knock events effectively # reduces what appear as multiple events according to sleep_interval and # update_threshold into a singular event if( $diffInterval > $INTERVAL_THRESHOLD ){ if( $knockCount == ){ $diffInterval = } if( $option ){ print Knock: $knockCount ## last: [$currVal] curr: [$prevInterval] ; print difference is: $diffIntervaln; } push @baseKnocks $diffInterval; $knockCount++; }# if the difference interval is greater than the threshold $prevInterval = $currVal; }#if checkknock passed }#knockListen
在創(chuàng)建敲打模式時(shí)該模式會(huì)被放入 ~/knockFile 文件中并使用下面的子程序進(jìn)行讀取
清單 讀取敲打文件
sub readKnockFile { open(KNCKFILE$ENV{HOME}/knockFile) or die no knock file: $!; while(){ if( !/^#/ ){ my @arrLine = split _#_; $knockHash{ $arrLine[] }{ cmd } = $arrLine[]; $knockHash{ $arrLine[] }{ comment } = $arrLine[]; }#if not a comment line }#for each line in file close(KNCKFILE); }#readKnockFile
當(dāng) knockListen 獲得敲打模式時(shí)它會(huì)將該模式與從 readKnockFile 中讀取的敲打模式進(jìn)行比較下面的 compareKnockSequences 子程序會(huì)對(duì)敲打之間的時(shí)間進(jìn)行簡(jiǎn)單的區(qū)別檢查注意敲打之間的差別并不是簡(jiǎn)單混合在一起的很多次敲打時(shí)的少量時(shí)間差別并不會(huì)累積成總體的匹配失效
第一個(gè)要比較的是敲打的次數(shù)因?yàn)槲覀儧](méi)有必要將一個(gè)七次敲打的序列與一個(gè)兩次敲打的序列進(jìn)行比較如果敲打的次數(shù)與 ~/knockFile 中現(xiàn)有的敲打序列匹配每次敲打之間的差別也少于最大敲打偏差那么這次敲打就可以認(rèn)為是完全匹配的在允許敲打序列進(jìn)行不精確匹配時(shí)最大敲打偏差非常關(guān)鍵我們可以增大最大敲打偏差來(lái)使敲打節(jié)奏更加自由但是要注意這可能會(huì)導(dǎo)致敲打模式匹配不正確例如我們可以在所期望的時(shí)間之前或之后半秒鐘允許自己的敲打模式發(fā)生偏離但這仍然可以匹配這樣就可以有效地說(shuō)明刮臉和理發(fā) 可以與 Mary 姓 Little Lamb 匹配因此在修改這個(gè)參數(shù)時(shí)一定要小心
如果完整的模式可以匹配就會(huì)運(yùn)行 ~/knockFile 中指定的命令如果啟用了冗余模式則會(huì)打印結(jié)果下一個(gè)步驟是如果沒(méi)有找到匹配項(xiàng)就退出這個(gè)子程序如果找到了匹配項(xiàng)就重置所記錄的敲打序列這個(gè)步驟會(huì)執(zhí)行 compareKnockSequences 子程序
清單 比較敲打序列
sub compareKnockSequences { my $countMatch = ; # record how many knocks matched # for each knock sequence in the config file for( keys %knockHash ){ # get the timings between knocks my @confKnocks = split; # if the count of knocks match if( $knockCount eq @confKnocks ){ my $knockDiff = ; my $counter = ; for( $counter=; $counter<$knockCount; $counter++ ){ $knockDiff = abs($confKnocks[$counter] $baseKnocks[$counter]); my $knkStr = k $counter b $baseKnocks[$counter] c $confKnocks[$counter] d $knockDiffn; # if its an exact match increment the matching counter if( $knockDiff < $MAX_KNOCK_DEV ){ if( $option ){ print MATCH $knkStr } $countMatch++; # if the knocks dont match move on to the next pattern in the list }else{ if( $option ){ print DISSONANCE $knkStr } last; }# deviation check }#for each knock }#if number of knocks matches # if the count of knocks is an exact match run the command if( $countMatch eq @confKnocks ){ my $cmd = system( $knockHash{@confKnocks }{ cmd } ); if( $option ){ print $cmdn } last; # otherwise make the count of matches zero in order to not reset }else{ $countMatch = ; } }#for keys # if the match count is zero exit and dont reset variables so a longer # knock sequence can be entered and checked if( $countMatch == ){ return() } # if a match occurred reset the variables so it wont match another pattern $knockCount = ; @baseKnocks = (); }#compareKnockSequences[!--empirenews.page--]
主程序的邏輯
利用這些子程序主程序的邏輯允許用戶創(chuàng)建敲打序列或在守護(hù)模式下監(jiān)聽(tīng)敲打序列并執(zhí)行命令第一部分是在用戶指定 c 選項(xiàng)(用于創(chuàng)建模式)時(shí)執(zhí)行的可以用簡(jiǎn)單的超時(shí)進(jìn)程來(lái)結(jié)束敲打序列增大最大超時(shí)長(zhǎng)度變量的值可以讓兩次敲打序列之間暫停 秒以上如果我們保留最大超時(shí)長(zhǎng)度為 秒那么程序運(yùn)行到這個(gè)時(shí)間時(shí)就會(huì)結(jié)束并打印當(dāng)前輸入的敲打序列
清單 創(chuàng)建序列主邏輯
if( $option eq c ){ print create a knock pattern:n; $startTime = getEpochSeconds(); # reset time out start while( $timeOut == ){ $currTime = getEpochSeconds(); # check if there has not been a knock in a while if( $currTime $startTime > $MAX_TIMEOUT_LENGTH ){ $timeOut = ; # exit the loop }else{ # if a knock has been entered before timeout reset timers so # more knocks can be entered if( $knockCount != $knockAge ){ $startTime = $currTime; # reset timer for longer delay $knockAge = $knockCount; # synchronize knock counts }# if a new knock came in }# if timer not reached knockListen(); select(undef undef undef $SLEEP_INTERVAL); }#timeOut = if( @baseKnocks ){ print place the following line in $ENV{HOME}/knockFilenn; for( @baseKnocks ){ print $_ } print _#_ (command here) _#_ nn; }#if knocks entered
第二部分是用來(lái)在一個(gè)無(wú)限循環(huán)中監(jiān)聽(tīng)敲打序列的主邏輯它在一個(gè)循環(huán)中大約要睡眠/ 秒在這個(gè)循環(huán)中還使用了一個(gè)基于秒的超時(shí)在足夠的延時(shí)之后重置敲打序列注意在這個(gè)例子中敲打監(jiān)聽(tīng)超時(shí)時(shí)間為 秒而最大超時(shí)時(shí)間為 秒這樣就提供了在敲打創(chuàng)建模式下進(jìn)行簡(jiǎn)單測(cè)試設(shè)置的功能并為敲打序列的監(jiān)聽(tīng)模式提供了一個(gè)快速重置選項(xiàng)
清單 主程序中的敲打監(jiān)聽(tīng)代碼
}else{ # main code loop to listen for knocking and run commands readKnockFile(); $startTime = getEpochSeconds(); while( $timeOut == ){ $currTime = getEpochSeconds(); if( $currTime $startTime > $LISTEN_TIMEOUT ){ $knockCount = ; @baseKnocks = (); $startTime = $currTime; if( $option ){ printlisten timeout resetting knocks n } }else{ if( $knockCount != $knockAge ){ $startTime = $currTime; # reset timer for longer delay $knockAge = $knockCount; # synchronize knock counts }# if a new knock came in compareKnockSequences(); }#if not reset timeout knockListen(); select(undefundef undef $SLEEP_INTERVAL); }#main knock listen loop }# if create or listen for knocks
警告安全性
knockAge 程序非常適合用于為系統(tǒng)提供一種額外的用戶輸入通道然而需要注意的是使用 knockAge 來(lái)做任何事都需要在系統(tǒng)上進(jìn)行認(rèn)證是的它可以防止密鑰記錄程序監(jiān)聽(tīng)密碼的問(wèn)題但是很多與 敲打認(rèn)證 有關(guān)的因素都表明在對(duì)安全性敏感的環(huán)境中使用這種技術(shù)還不夠成熟敲打序列目前是以 到 個(gè)數(shù)字在 ~/knockFile 中進(jìn)行存儲(chǔ)的它們以毫秒為單位來(lái)表示延時(shí)這個(gè) 密碼 文件非常容易讀取并且通過(guò)嘗試和匹配敲打模式可以獲得對(duì)系統(tǒng)的訪問(wèn)權(quán)限排除毫秒值中一些精度是一種可用的方法但是這種練習(xí)就留給那些希望自行對(duì)系統(tǒng)風(fēng)險(xiǎn)進(jìn)行評(píng)估的讀者好了
在任何敏感環(huán)境中我們都應(yīng)該進(jìn)行一些研究判斷用戶是否有足夠的應(yīng)變能力并能夠精確地重現(xiàn)敲打序列例如我們是否具有能力創(chuàng)建并連續(xù)輸入可接受長(zhǎng)度的敲打密碼?具有普通智商的人是否可以直觀地使用這種敲打序列?或者我們是否準(zhǔn)備使用 刮臉和理發(fā)操作 來(lái)作為密碼?