[轉載]BCB:Put DLL File into EXE File


ref


BCB:Put DLL File into EXE File

把 DLL File 存放於應用程式裡,在應用程式是很常用的技巧,這個方法可以讓程式設計者只需給使用者一個執行檔就可以,不需再給DLL File。就不需要擔心使用者忘了把應用程式 和 DLL File 放在同一個目錄之下。有些程式設計者會使用InstallShield 把應用程式和DLL整合在一起來解決這個問題,而我們是把DLL放到執行檔的資源裡。

在PE格式的執行檔包含了資源,CODE 和 DATA,其中資源可以是文字(EX:版權宣告),圖片,ICON,動畫及二進制檔,我們就是把 DLL FILE 或者 DRIVER 宣告成二進制檔放到執行檔的資源中。

1.下載免費軟體 ResEdit
1-1. 開啟 ResEdit 選擇 File-> New project -> Resource Script File Name (.RC)
1-2. 在 Resources 欄位中,選擇 Add Resources ... -> User Defined -> Name identifier -> 輸入 RCDATA -> 選擇你的 DLL File.
1-3. 選擇檔案儲存,一共會有二個檔案,一個為 Resource.h 及 .RC FILE。

2. 打開 BCB 並開啟你的專案,選擇 View/Project Manager 開啟Project Manager DIALOG,將 .RC File 加入到你的專案中

在 Unit1.cpp 中,加入以下的程式碼
#include "resource.h"

typedef int (*GETNAME)(void); // DLL Function Name

void __fastcall TForm1::Button2Click(TObject *Sender) 
{
  HINSTANCE hinstApp;
  hinstApp=LoadLibrary(ExtractFileName(Application->ExeName).c_str());
  if(hinstApp!=NULL) {
      TResourceStream *rcStream=new
      TResourceStream ((int)hinstApp,IDR_RCDATA1,  RT_RCDATA);
      rcStream->SaveToFile("Naming.dll");
      HINSTANCE hinstDll;
      hinstDll=LoadLibrary("Naming.dll");
      if(hinstDll!=NULL) {
          GETNAME getName;
          int NameId=0;
          getName=(GETNAME)GetProcAddress(hinstDll,"_getName");
          if(getName!=NULL) {
              NameId=getName();
              ShowMessage(IntToStr(NameId));
          }
          FreeLibrary(hinstDll);
     }
     delete rcStream;
     FreeLibrary(hinstApp);
 }
}

[轉]How to compile Android Device Driver as a Module(.ko)


How to compile Android Device Driver as a Module(.ko)

Here are the quick steps to be followed.

Prerequisite:
1. kernel sources from vendor say HTC wildfire(2.1 update-1)
2. Android source code for Éclair
3. Create a new folder called Kernel and copy the contents from the sources download via vendor

Step1: Copy config.gz from running hardware

adb pull /proc/config.gz
gunzip config.gz
mv config .config


Step 2: Copy/Overwrite the .config file to the kenel root directory

open .config file and search for
CONFIG_MODULE_NAME1=y
CONFIG_MODULE_NAME2=y


and replace 'y' with 'm', we use CONFIG_MODULE_NAME1 as module

CONFIG_MODULE_NAME1=m
CONFIG_MODULE_NAME2=y

Step 3: Check the active kernel version on the hardware using 'OR' if you are using own Boot.img then skip this and move on to step 4:

adb shell
# uname -a

or you may get the details of the kernel from the Settings->Aboutphone->SoftwareInformation: Kernel version

2.6.29-6fb59e13 HTC-kernel@xxxxxxxx

open Makefile in the kernel folder, search and replace "EXTRAVERSION =" with "EXTRAVERSION =-6fb59e13"

Step 4: Set the Env variables

export ARCH=arm
exprot CROSS_COMPILE=arm-eabi-
export PATH=$PATH:~/eclair/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/


now perform make modules for make from the kernel sources

kernel:$ make modules or make

after successful compilation, check out the .ko files next to the sources in the same directory

Complete example: How to get LG headset sources compile in to kernel module(.ko)
ref: http://android-jotting.blogspot.tw/2010/12/how-to-compile-android-device-driver-as.html

Mac 終端機顏色設定

对于从Unix/Linux平台转到Mac的同学来说,“终端”是经常要使用的一个工具。不过可能有很多人已经发现了,当我们使用ls命令来显示目录内容的时候,“终端”对于目录、可执行文件等特殊类型的文件并没有使用颜色来显示,只有使用“ls -G”时,才能显示颜色,这可真是不方便啊。有没有方法可以默认显示颜色呢?方法当然有。

方案一

第一个方案是让ls自动变成ls -G。我们要在用户目录下(~)创建一个名为.bash_profile的文件,如果这个文件已经存在,我们直接编辑这个文件就可以了。在~/.bash_profile中加入下面的内容:

alias ls=”ls -G”
保存文件后,重新启动“终端”。这时,运行ls命令,我们就可以看到文件已经可以用彩色来显示了。



方案二

上面这个方案虽然解决了彩色显示问题,但是还有一点不足,就是无法设置显示的颜色。比如说,我想用红色显示目录,那么这种方法是做不到的。下面我们来看看一个更好的解决方案。同样是修改~/.bash_profile文件,在文件中加入下面两行配置。

export CLICOLOR=1
export LSCOLORS=gxfxaxdxcxegedabagacad
保存文件,重新运行“终端”,我们发现目录的颜色由蓝色变成了青色。

 

配置

那么应该怎样来配置成我喜欢的颜色呢?下面我们就来详细说一些这些配置。

~/.bash_profile是bash shell中当前登录用户的配置文件。bash是“终端”中默认的shell。

alias ls=”ls -G”是给”ls -G”起了一个别名,当执行ls时,就相当于执行了ls -G。

CLICOLOR是用来设置是否进行颜色的显示。CLI是Command Line Interface的缩写。

LSCOLORS是用来设置当CLICOLOR被启用后,各种文件类型的颜色。LSCOLORS的值中每两个字母为一组,分别设置某个文件类型的文字颜色和背景颜色。LSCOLORS中一共11组颜色设置,按照先后顺序,分别对以下的文件类型进行设置:

directory
symbolic link
socket
pipe
executable
block special
character special
executable with setuid bit set
executable with setgid bit set
directory writable to others, with sticky bit
directory writable to others, without sticky bit
LSCOLORS中,字母代表的颜色如下:

a 黑色
b 红色
c 绿色
d 棕色
e 蓝色
f 洋红色
g 青色
h 浅灰色
A 黑色粗体
B 红色粗体
C 绿色粗体
D 棕色粗体
E 蓝色粗体
F 洋红色粗体
G 青色粗体
H 浅灰色粗体
系统默认颜色
所以,如果我们想把目录显示成红色,就可以把LSCOLORS设置为bxfxaxdxcxegedabagacad就可以了 


所以对照这张表就可以得知:
bxfxaxdxcxegedabagacad
就是对于directory而言,它的前景色就是: b(red),而背景色就是:x(默认的背景色).

[轉載] Developing for Linux under MacOSX using Xcode

[ref]: http://ricardo-dias.com/2012/01/08/developing-for-linux-under-os-x-in-xcode/


In this mini-article I will show you how I develop applications for Linux in XCode 4. At the moment I’m using XCode 4.2.1, in OSX Lion, with Ubuntu 10.04 running on a virtual machine.
Although the article is related to XCode, after reading and trying out for yourself, you will notice that you can use whatever IDE you like. Here I’m just showing you how you can code in a OSX-only IDE and deploy in Linux.

Requirements

You will need some tools before we start:
  • VMWare or similar virtual machine application for Mac
    • Used to run our Linux system, and that’s where we will compile and run the target application.
      You can also use a physical computer instead. However, you will need network connectivity from mac to that computer because the communication between this linux System and our Mac is done by SSH.
  • OSXFuse
    • Requirement for the next point
  • SSHFS
    • It will be used to mount a remote directory in our Mac, and access it as if it was an external hard disk drive
Once you have all these, we are ready to go, but take some seconds to make sure you can compile the application in your slave Linux system. This will ensure that any problems you may encounter are not related to your slave machine or the code you are trying to compile.

Accessing slave machine using SSH

Now you will need the slave machine’s IP address, typing ifconfig in its Terminal.
As you can see in the image above, in my case I’ll be using 172.16.68.128 as the slave’s IP Address.
Then we make sure we can access it from your Mac typing the next command in Mac Terminal:
ssh username@ip
If we are asked for the password, then we got a valid SSH connection and we can move on…

Adding an alias for the Linux Slave IP

Because IPs can change sometimes, even inside Local Area Network, I added an alias for this IP, so that I could use it in scripts instead of the IP address itself. When it changes, I only have to modify one single file. You can do the same, by editing the hosts file, so grab the Mac Terminal and type as you see:
sudo vim /etc/hosts
Add a new line in the end, pressing I to enter insert mode:
172.16.68.128 vmcode
Now press ESC to exit “INSERT mode” and type :wq (yes, including the colon). If you have any problems using vim to edit this file, you can try nano instead – just replace “vim” with “nano” in the first command of this section. Now, you can use the virtual hostname “vmcode” instead of the real IP (which will be a lot easier to remember).

Setup script files

Now we need to setup two script files. I called them mountDir and sshbuild. The first one will mount the remote directory in our Mac and the latter is used to remotely compile the application.
Firstly pick a directory for these scripts, where you need to place the sshfs-static-leopard file, because it will be needed for the mountDir script.

Mounting Directory Script

Using your favorite text editor, create a new file called “mountDir” (no extension), and paste the following code:
#!/bin/bash
echo password | ./sshfs-static-leopard username@vmcode:codedir ~/path/to/mount/dir -o password_stdin
I’m explaining some of the variables in the command, that you should change to fit your needs:
  • username and password are the credentials for the user in the slave Linux machine
  • codedir is the directory in slave machine you want to mount in Mac
  • ~/path/to/mount/dir is the path to the Mac’s directory where you want to mount the slave’s directory
If you are using a real box instead of a VM, I recommend you configure ssh public keys instead of storing your password in plain text. You SHOULD NOT use the same password as of your Mac User
This was pointed by reader Daid, and I explained him I used it in plain text because I’m connecting to this VM, used only for compiling purposes and not accessible from outside, so I’m not that worried about it.

Building remotely

The SSH command accepts a second argument, that is the command you want to execute right after the remote login. Save and create another file called “sshbuild” with the following content:
#!/bin/bash
ssh username@vmcode 'cd codedir; make'
Note that username and codedir must match the ones you used before.

Setting up XCode

Before we move to XCode, you first need to mount the directory: open the Terminal, cd to your scripts dir, and run sh mountDir. Now you should see the contents of remote dir in your Mac’s ~/path/to/mount/dir.
Any change you make to these files will be reproduced in the remote slave system (our VM), because SSHFS will be syncing in real-time.
Start XCode, then click File > New > New Workspace… and chose a location for the workspace file (I used the same as the scripts). You should see a window with three different spaces, they should have texts in the middle, from left ro right, saying “No Files”“No Editor” and “No Selection”. Open a Finder window in the location ~/path/to/mount/ and then drag the subfolder that has a name starting with “OSXFUSE” to the “No Files” space in XCode.
A popup will show up. Firstly, XCode will prompt you about your build tool. You should type the complete path to the sshbuild script, starting on root, on the “Build Tool” field.
After clicking “Next”, you will be presented something like the image below, you should select the second option, which is “Create folder references for any added folders”.
Basically you are adding a reference to that directory, so instead of working in a local copy, you will edit the remote files directly. Now that you have all the directories in the slave’s codedir in the left panel of XCode, you can now open, edit and save any of your files using XCode. Now hit Command+B to run the build tool, and if everything goes well, you should see a message box saying Build Successful.

Running the Application

As you are developing for Linux, you should preferably debug under Linux. However, I often use an Application called X11, taht can be found in your Applications/Utilities folder. Type this command under X11 console window and the application should run in your Mac as if it was on Linux, even if it needs to open windows:
ssh -X username@vmcode
cd codedir./application

Conclusion

Here I shown you how I develop applications for Linux using the resourceful XCode and all it’s features, without quitting Mac OSX. I hope you found it useful and it helps you by increasing your productivity. Leave a reply, share your thoughts and suggestions and happy coding ;)

– edit 11/01/2012 –
After reading this article, Simon Elliston Ball posted a reply with a link to his blog suggesting a different solution – vagrant – that let’s you achieve the same results, but storing your files on Mac instead of the Linux system. I believe there are some advantages of doing this way, so you may choose the solution that best fits your needs. Thank you Simon.

Missing Library folder in Mac OS X Lion


Problem
In your home folder, you notice that there is no longer a Library folder.
Cause
This is the default setting by design in Mac OS X Lion.
SolutionTo get your Library folder back:
  1. Go to your Applications folder.
  2. Go to the Utilities folder.
  3. Double click on Terminal.
  4. Select all the text in the box below and press cmd + C to Copy.
    chflags nohidden ~/Library
  5. In the Terminal window press cmd + V or click Edit > Paste (on the top menu).
  6. Press Enter.
To revert back to the default setting change “nohidden” to “hidden” in Step 4.

[轉載]Best practicing for password protection



如何有效保護用戶密碼的議題,估計在網路上討論不下數千次。本篇文章除了整理並分析何種方式是個 "壞方法" 外,也希望經過不斷的思考來理出最佳的解決方案(Best practices)。
本篇文章標題取用 "Best practicing" 而非 "Best practices" 的意義,在於內容所建議的方法,目前可能並非是最佳解決方案,未來若有更好的方法也將持續更新本篇的內容。

前言

現在做 "好" 一個網路應用是非常困難的事 (前提是如果 "想" 做好的話)。因為單是如何保護好客戶的密碼,就是一門大學問。
首先,我們要思考的是 "是否有必要儲存客戶的密碼在我們的系統中"? 如果將認證的系統由他方服務提供而不會影響商業模式的運作時,那麼與其它系統整合會是個比較好的,例如使用 Facebook 的帳號登入網站或系統的認證方式。
反之,如果決定要自行建置,則考量點就會有很多。除了需要考量安全性外,還需要考慮效能的問題,因為 "通常" 安全性高的同時也伴隨著低效能的壞處。這意謂著同樣是數萬人上線的網站,若選擇安全性高的方法,可能會比安全性低的方法額外需要更多的機器來運作。
另外在資料外洩的議題上,本篇將討論 "資料庫外洩" 以及 "資料庫與網站程式皆外洩" 的兩種情形,後者在網路上是目前比較少人探討的議題。有時資料外洩的並不只是資料庫的資料,更嚴重的是除了資料庫外,連整個網站的程式也一併遭到竊取,而這兩種情形面對著不同層級的威脅。
然而一旦資料外洩後,有心人士可以依照密碼保存的方式,決定採用 "Unhash/Decrypt attacks" 或 "Statistics attacks" 等攻擊方式。不管是何種方式,目的就是希望能夠還原用戶的密碼,而我們想做的就是盡量降低被還原的可能性。
以下是筆者整理的常見方法及其分析。

儲存用戶密碼之方法

1. 明碼(plaintext)

最簡單的保存方式,就是將用戶註冊時所輸入的密碼,不經過任何的處理,原封不動的儲存在資料庫中。例如密碼為 "123456",在資料庫中則以 "123456" 儲存。然而這種簡單的方式也是最危險的。
例如,用戶 ant 帳號所使用的密碼為 "123456", 則在資料庫中以 "123456" 儲存,如下:
資料庫
================================================
姓名       | 密碼
ant        | 123456
如果資料庫外洩時,任何人都可以直接看到所有用戶的密碼。另一個問題是,只要是有權限瀏覽資料庫的人,也幾乎都可能隨時取得用戶的密碼,例如資料庫管理員或甚至是程式設計師。
這種方式不管是面對 "資料庫外洩" 或 "資料庫與網站程式皆外洩" 的情形都沒有任何防護措施,因此明碼是最不建議使用的方式。

2. 簡易雜湊法 (Pure Hash)

演算法為: Hash(明碼)。
雜湊法 (Hash) 可以視為一數學函式,專職將某值轉換成另一值。常見的雜湊法有很多,例如 MD5, SHA1 等。
假設選定為 MD5, 在實際操作上,當用戶註冊的密碼為 "123456" 時,此時會先將 "123456" 經由 MD5 函式運算,也就是 MD5(123456) 會得到 "f447b20a7fcbf53a5d5be013ea0b15af" 結果,再將 "f447b20a7fcbf53a5d5be013ea0b15af" 值寫入資料庫中,而不是將明碼 "123456" 寫入資料庫。
資料庫
================================================
姓名       | 密碼
ant        | f447b20a7fcbf53a5d5be013ea0b15af
當下次該用戶嘗試登入時,會將輸入的值經過 MD5 函式運算後,再與資料庫的值進行比對,如果字串完全符合則表示用戶輸入了正確的密碼,進而允許用戶登入網站或系統。所以當用戶以 "ant" 為用戶名及密碼為 "123456" 登入時,則網站或系統會先將 "123456" 以 MD5 函式運算後得值為 "f447b20a7fcbf53a5d5be013ea0b15af",再使用 "姓名=ant AND 密碼=f447b20a7fcbf53a5d5be013ea0b15af" 為搜尋值於資料庫中查詢。
整個密碼的處理流程中,明碼 "123456" 將不會永久性的儲存在系統或資料庫中,而可避免資料庫人員在瀏覽資料庫時,可以直接看到明碼的情形。另外當使用這種方式保存密碼時,如果資料庫外洩時,對方取得的密碼欄位會是 "f447b20a7fcbf53a5d5be013ea0b15af" ,而不是明碼 "123456"。
取得資料庫的有心人士若想要知道原本的明碼,就需要解譯 "f447b20a7fcbf53a5d5be013ea0b15af" 的還原值為何,這在數學原理中是比較困難的。因為雜湊 )(Hash) 演算法是一種單向 (one-way) 運算函式,在原理上是難以從計算值推回原先的值,也就是幾乎無法由 "f447b20a7fcbf53a5d5be013ea0b15af" 經運算逆推回 "123456",進而保護了所有用戶的原始密碼。
雖然從這點上看起來比明碼的方式好太多了,但仍然存在著弱點,例如目前常見的 "查表法" 式的攻擊。簡單來說,攻擊者可以事先準備好所有可能性的 MD5 清單表,如:
查表資料庫
================================================
Hash                             | 明碼
286755fad04869ca523320acce0dc6a4 | password
9aa2a870d0001ea6569ec7ab579bd409 | iloveyou
f447b20a7fcbf53a5d5be013ea0b15af | 123456
如此攻擊者只需要把 "f447b20a7fcbf53a5d5be013ea0b15af" 值於資料庫中查詢即可馬上比對出明碼為 "123456",進而得知該用戶的密碼。所以理論上,只要查表資料庫夠齊全(即收集夠多的明碼對照表),即可把解譯任何雜湊 (Hash) 值。所以,簡易雜湊法仍然不夠安全。

3. 加料式雜湊法 (Salted Hash)

演算法為: Hash(亂定值 + 明碼)。
面對 "查表法" 類的攻擊時,最直覺的方法就是增加查表的困難度。我們知道查表資料庫理論上可以收集所有可能之明碼的雜湊 (Hash) 值,但在實作上是有困難度的,因為攻擊者在空間與時間上,不太可能收集 "所有" 可能的查表值,而是僅盡量收集常見的對照值,例如 "password", "123456" 等。因此,在這種限制下,查表資料庫 "通常" 不會收錄較無規則或看似亂碼的明碼值,例如 "i3flm234rmsldk543kf2jvl2sdfj123456",這也是認定用戶通常不會真的將這麼難記的值當作密碼。
於是在防護手法上,網站或系統可以 "自動" 替用戶密碼添加 "亂定數" (salty),如 "i3flm234rmsldk543kf2jvl2sdfj"。在這種情況下,當用戶使用 "123456" 密碼註冊時,程式會將 "亂定數" 加上其密碼後,才經由雜湊 (Hash) 函式運算,再儲存至資料庫中。如 MD5("i3flm234rmsldk543kf2jvl2sdfj" + "123456"),得出值為 "d0a970cc71d15aa10b07584a7bd31ff6"。
資料庫
================================================
姓名       | 密碼
ant        | d0a970cc71d15aa10b07584a7bd31ff6
因此當用戶下次登入時,輸入密碼 "123456" 後,程式會再 "自動" 替用戶密碼添加 "亂定數" (salty),成為 MD5("i3flm234rmsldk543kf2jvl2sdfj" + "123456") 來運算,則得出的值就會與資料庫的值一樣。這種防護方法就是賭定查表資料庫不會有 "亂定數" 為首的對照表。以此例來說,就是賭查表資料庫沒有 "i3flm234rmsldk543kf2jvl2sdfj" + "123456" 的對照表。
加料式雜湊法 (Salted Hash) 加強原本簡易雜湊法的安全性,加上操作簡單的特性,所以目前成為最常見的密碼保護方式。不過筆者要提醒的是,這種方法是基於賭上查表資料庫 "可能" 不會有 "亂定數" 前提下的保護策略,所以 "亂定數" 取值就變得非常重要,例如值不得太短,且值必須不是常見的值(盡量是亂數或近乎亂數產生的值)。
另外,加料式雜湊法的另一個前提是,網站或系統程式碼未遭受外洩。如果入侵行為導致除了資料庫外,程式也一併外洩時,此時有心人士可以從程式碼中得知 "亂定數" 之值,那麼依然可以有效地利用 "查表法" 進行解譯的攻擊。
例如,有心人士手中的查表資料庫如下:
查表資料庫
================================================
Hash                             | 明碼
286755fad04869ca523320acce0dc6a4 | password
9aa2a870d0001ea6569ec7ab579bd409 | iloveyou
f447b20a7fcbf53a5d5be013ea0b15af | 123456
此時從網站或系統程式碼中,發現 "亂定數" 為 "i3flm234rmsldk543kf2jvl2sdfj",則可以據此來重新產生查表資料庫的對照值,例如原本的 "password" 明碼,改用 MD5("i3flm234rmsldk543kf2jvl2sdfj" + "password") 來取值,以此類推從而產生針對此資料庫的查表資料庫:
查表資料庫
================================================
Hash (i3flm234rmsldk543kf2jvl2sdfj) | 明碼
d2e117dc74cd54576bec9fd4fd6a8b1e    | password
5d622aeb7d27752e72c8ca628f048ac0    | iloveyou
d0a970cc71d15aa10b07584a7bd31ff6    | 123456
此時,再用原本查表式的攻擊時,就很容易找到 "d0a970cc71d15aa10b07584a7bd31ff6" 的對照值為 "123456"。

4. 加密方法 (Encrypted Password)

演算法為: Encrypt(明碼, 金鑰值)。
有些人會使用加解密的方式來保護密碼,例如 DES, AES 等。但這種方法的問題也不少,第一,加密耗用的資源比單一雜湊 (Hash) 演算法多;第二,加密金鑰需妥善保管,否則知道金鑰的人都可以解出所有用戶的密碼;第三,如果資料庫、程式與金鑰外洩,則此防護方式等同虛設,因為有心人士不需查表就可以直接用解密的方式還原密碼。
因此,筆者認為除非有完善的配套措施,否則不建議使用此種保護方法。

5. 複合式雜湊法

基於加料式雜湊法 (Salted Hash) 可以衍生出許多不同的變形。

A. "亂定數" 使用兩次以上

其中一種演算法為: 亂定數 + Hash(亂定數 + 明碼)。
延伸先前舉例的 "i3flm234rmsldk543kf2jvl2sdfj" 亂定數,則雜湊值為 "i3flm234rmsldk543kf2jvl2sdfj" + MD5("i3flm234rmsldk543kf2jvl2sdfj" + "123456"),並得其值為 "i3flm234rmsldk543kf2jvl2sdfj" + "d0a970cc71d15aa10b07584a7bd31ff6"。
這種複合式雜湊法加強的是查表資料庫的困難度,但是仍然沒有解決若程式一併外洩時的問題,因為有心人士從程式碼中得知 "亂定數" 後,可以直接將 "亂定數" 去除,進而留下 "d0a970cc71d15aa10b07584a7bd31ff6"。如此強度與加料式雜湊法 (Salted Hash) 是差不多的。

B. 使用兩種以上的加料式雜湊演算法

其中一種演算法為: MD5(SHA1(亂定數 + 明碼))。
以 PHP 程式語言為例:
$salty = "i3flm234rmsldk543kf2jvl2sdfj";
$password_hash = md5(sha1($salty + $password));
這種複合式雜湊法加強的是查表資料庫的困難度,因為要建立這種查表資料庫需要耗用較多的運算資源(因為使用兩次雜湊演算法),但相對而言,比加料式雜湊法 (Salted Hash) 來得安全許多。但是最大的缺點就是我們網站或系統的運算資源也會耗用較多。
因此,有心人士取得資料庫及網站程式時,即使在知道 "亂定數" 的條件下,要重新產生查表資料庫也是一件很耗資源的事情。

6. HMAC 加料式演算法

其中一種演算法為: HMAC(SHA1, 亂定數 + 明碼, 金鑰值)。
以 PHP 程式語言為例:
$key = "146c07ef2479cedcd54c7c2af5cf3a80";
$salty = "i3flm234rmsldk543kf2jvl2sdfj";
$password_hash = hash_hmac("sha1", $salty + $password, $key);
HMAC 演算法有著加料式及加密方法的優點,使得查表式攻擊的成本以等比級數倍增,但因為 HMAC 耗用的資源更多,所以運算量要求最大,這也會造成網站或系統的負載需求更高。

統計特徵值的攻擊方法

排除不建議或類似的防護方法,筆者建議的是 "加料式雜湊法 (Salted Hash)", "使用兩種以上的加料式雜湊演算法" 或 "HMAC 加料式演算法",但若您有著更高安全的需求,則建議採用後面兩者。
另外,筆者在前言中有提到 "Statistics attacks",此種攻擊方式是針對 "亂定數" 的手法。以前例的 "加料式雜湊法 (Salted Hash)" 來說,所有的用戶密碼皆是加上 "定數" 來處理,例如 "i3flm234rmsldk543kf2jvl2sdfj",則用戶 ant 的密碼 "123456" 在資料庫會是:
資料庫
================================================
姓名       | 密碼
ant        | d0a970cc71d15aa10b07584a7bd31ff6
我們知道 "123456" 其實是個常見的密碼,所以如果網站或系統的用戶數夠多,那麼我們可以假設 "123456" 為密碼的用戶比例,就會存有顯著的統計特徵值,例如資料庫可能為:
資料庫
================================================
姓名       | 密碼
ant        | d0a970cc71d15aa10b07584a7bd31ff6
member     | 3kjose9r2jfljvl2j4lksdjfljwo3rda
guest      | d0a970cc71d15aa10b07584a7bd31ff6
newbie     | d0a970cc71d15aa10b07584a7bd31ff6
這意謂著 ant, guest 及 newbie 的密碼因為都是 "123456" 所以其值皆相同。此時就算僅有資料庫外洩,有心人士依然可以取得其統計特徵值,來猜測最多人使用的 "123456" 來進行猜 "亂定數" 的破解,而只要解譯 "亂定數" 後再取得明碼就不難了。
因此為了防止 "Statistics attacks",加料 (Salted) 的東西就不能是個 "定數" 而必須是個 "隨機數",且這個隨機數需依每個人有所不同。例如 ant 的隨機數是 "i3flm234rmsldk543kf2jvl2sdfj", 而 guest 的隨機數是 "43kf2jvl2sdfji3flm234rmsldk5",那麼即使 ant 及 guest 的明碼是一樣的,儲存在資料庫的 Hash 值仍然是不一樣的。"隨機數" 的值可以是亂數產生,然後儲存在某一資料庫欄位,以利事後的比對,或者直接取用原本用戶資料表裡的唯一值,例如註冊時間也可以。
最後,如果擔心 "Collision attacks" 的話,上述所有方法皆可以將 MD5 或 SHA1,改成更複雜的 SHA256 或 SHA512,但是運算資源也會倍增。

總結

在安全性及效能的綜合考量下,筆者建議 "隨機加料式雜湊法", "使用兩種以上的隨機加料式雜湊演算法" 或 "HMAC 隨機加料式演算法"。愈後者安全性愈高,但效能的要求也愈高。

1. 隨機加料式雜湊法

演算法為: Hash(隨機數 + 明碼)。
當 Hash 為 MD5 時,用戶 ant 之密碼為 "123456",系統會隨機產生一隨機數為 "i3flm234rmsldk543kf2jvl2sdfj",則經運算後密碼以 "d0a970cc71d15aa10b07584a7bd31ff6" 儲存。當用戶 guest 之密碼為 "123456",系統會隨機產生另一隨機數為 "43kf2jvl2sdfji3flm234rmsldk5",則經運算後密碼以 "171773b4cbdc81b0e697ab3c21a7366d" 儲存。
資料庫
============================================================================
姓名  | 密碼                             | 隨機數
ant   | d0a970cc71d15aa10b07584a7bd31ff6 | i3flm234rmsldk543kf2jvl2sdfj
guest | 171773b4cbdc81b0e697ab3c21a7366d | 43kf2jvl2sdfji3flm234rmsldk5

2. 使用兩種以上的隨機加料式雜湊演算法

演算法為: Hash1(Hash2(隨機數 + 明碼)。
當 Hash1 為 MD5 且 Hash2 為 SHA1 時,用戶 ant 之密碼為 "123456",系統隨機產生的隨機數為 "i3flm234rmsldk543kf2jvl2sdfj",則經運算後密碼以 "1a2379a1f4e28eacb9151734f3773b23" 儲存。當用戶 guest 之密碼為 "123456",系統隨機產生的另一隨機數為 "43kf2jvl2sdfji3flm234rmsldk5",則經運算後密碼以 "0332d18e7e836c4df785641b4ac198cd" 儲存。
資料庫
============================================================================
姓名  | 密碼                             | 隨機數
ant   | 1a2379a1f4e28eacb9151734f3773b23 | i3flm234rmsldk543kf2jvl2sdfj
guest | 0332d18e7e836c4df785641b4ac198cd | 43kf2jvl2sdfji3flm234rmsldk5

3. HMAC 隨機加料式演算法

演算法為: HMAC(Hash, 隨機數 + 明碼, 金鑰值)。
當 Hash 為 SHA1,Key 為 "mykey" 時,用戶 ant 之密碼為 "123456",系統隨機產生的隨機數為 "i3flm234rmsldk543kf2jvl2sdfj",則經運算後密碼以 "466b2528c18f4f0893be264bcc16d95d63053054" 儲存。當用戶 guest 之密碼為 "123456",系統隨機產生的隨機數為 "43kf2jvl2sdfji3flm234rmsldk5",則經運算後密碼以 "d7b9f21f0740e12a80e7f2cbb0df9a7f5c98bece" 儲存。
資料庫
===============================================================================
姓名  | 密碼                                     | 隨機數
ant   | 466b2528c18f4f0893be264bcc16d95d63053054 | i3flm234rmsldk543kf2jvl2sdfj
guest | d7b9f21f0740e12a80e7f2cbb0df9a7f5c98bece | 43kf2jvl2sdfji3flm23

虹光大成就-密教灌頂(一)