手機的短信加解密(一)
轉載http://www.ophonesdn.com/article/show/133
標簽 : 短信 加解密 DES 安全 密碼學
?
前言
????? 隨著手機功能的豐富及手機與日常生活的緊密關系,手機信息安全問題越來越成為人們關注的焦點。手機內部信息的泄露、被竊取、遺失或被盜,都會造成重大安全隱患。隨著3G時代的來臨,手機的高普及率使得手機與個人的生活隱私、商業活動緊密相關,手機的使用安全和隱私安全問題已經突顯出來。手機作為一個日益重要的信息載體,如何對其內部及通訊過程中的敏感信息進行有效保護,已經成為亟待解決的問題。
?
一、密碼學概述【1】
???? 使消息保密的技術和科學叫做密碼編碼學。
?
1.1 密碼學基礎
????????? 在密碼學中,明文用M(消息)或P(明文)表示,它可能是比特流(文本文件、位圖、數字化的語音流或數字化的視頻圖像)。至于涉及到計算機,P是簡單地二進制數據(除了這一章節外,這本書本身只涉及二進制數據和計算機密碼學)。明文可被傳送或存儲,無論在哪種情況,M指待加密的消息。密文用C表示,它也是二進制數據,有時和M一樣大,有時稍大(通過壓縮和加密的結合,C有可能比P小些。然而,單單加密通常達不到這一點)。加密函數E作用于M得到密文C,用數學表示為:
?
E(M)=C.
?
????????? 相反地,解密函數D作用于C產生M
?
D(C)=M.
?
?????????先加密后再解密消息,原始的明文將恢復出來,下面的等式必須成立:
?
D(E(M))=M
?
1.2 密碼學功能
????????? 除了提供機密性外,密碼學通常有其它的作用:.
-鑒別:消息的接收者應該能夠確認消息的來源;入侵者不可能偽裝成他人。
-完整性:消息的接收者應該能夠驗證在傳送過程中消息沒有被修改;入侵者不可能用假消息代替合法消息。
-抗抵賴:發送者事后不可能虛假地否認他發送的消息。
?
1.3 算法和密鑰
???????? 如果算法的保密性是基于保持算法的秘密,這種算法稱為受限制的算法。受限制的算法具有歷史意義,但按現在的標準,它們的保密性已遠遠不夠。大的或經常變換的用戶組織不能使用它們,因為每有一個用戶離開這個組織,其它的用戶就必須改換另外不同的算法。如果有人無意暴露了這個秘密,所有人都必須改變他們的算法。
現代密碼學用密鑰解決了這個問題,密鑰用K表示。K可以是很多數值里的任意值。密鑰K的可能值的范圍叫做密鑰空間。加密和解密運算都使用這個密鑰(即運算都依賴于密鑰,并用K作為下標表示),這樣,加/解密函數現在變成:
?
EK(M)=C
DK(C)=M.
?
?????? 這些函數具有下面的特性:
?
DK(EK(M))=M.
?
?????? 有些算法使用不同的加密密鑰和解密密鑰,也就是說加密密鑰K1與相應的解密密鑰K2不同,在這種情況下:
?
EK1(M)=C
DK2(C)=M
DK2 (EK1(M))=M
?
???????所有這些算法的安全性都基于密鑰的安全性;而不是基于算法的細節的安全性。這就意味著算法可以公開,也可以被分析,可以大量生產使用算法的產品,即使偷聽者知道你的算法也沒有關系;如果他不知道你使用的具體密鑰,他就不可能閱讀你的消息。
?
1.4 簡單異或
???????異或在C語言中是“^”操作,或者用數學表達式⊕表示。它是對比特的標準操作:
?
0⊕0 = 0
0⊕1 = 1
1⊕0 = 1
1⊕1 = 0
?
?????? 參照《OPhone手機基礎信息與基礎業務》(http://www.ophonesdn.com/article/show/102),中的短信發送功能。我們選擇0x55(0b01010101)作為密鑰,和每一個字節做異或運算,實現加解密。這個算法可以用下列代碼來實現,
view plain copy to clipboard print ?
for(int?i=0;i<msg.length();i++)?encrymsg[i]=(char)?(msg.charAt(i)^'U');???
for(int i=0;i<msg.length();i++) encrymsg[i]=(char) (msg.charAt(i)^'U'); //U的ASCII碼為0x55 msg=String.valueOf(encrymsg); sms.sendTextMessage(number, null, msg, pi, null);
????? 在發送端輸入明文“helloworld”,短信經過加密如圖1所示,變成了不可讀的亂碼。當我們將密文和0x55再次異或之后,可以獲得原始的明文。這就實現了異或加解密。
?
1.5 不安全的異或
????????? 這種方法沒有實際的保密性,這類加密可以通過下列兩部被輕松破譯。(1)用重合碼計數法找出密鑰長度。(2)按那個長度移動密文,并且和自己異或:這樣就消除了密鑰,留下明文和移動了密鑰長度的明文的異或。
1.6 分組密碼介紹
?????? 由于古典密碼學(異或屬于其中一種)在現在的計算機面前顯得不堪一擊,現代密碼學開始發展?,F代密碼學中有對稱密碼、消息摘要函數、公鑰密碼(用于數字簽名)等領域。本文通過循序漸進的辦法,介紹加解密在手機信息安全中的應用,首先介紹的是分組密碼。
?
?????? 分組密碼取用明文的一個區塊和鑰匙,輸出相同大小的密文區塊。由于信息通常比單一區塊還長,因此有了各種方式將連續的區塊編織在一起。 DES和AES是美國聯邦政府核定的分組密碼標準,本文主要介紹DES算法?!?】
?
??????? DES對64(bit)位的明文分組M進行操作,M經過一個初始置換IP置換成m0,將m0明文分成左半部分和右半部分m0=(L0,R0),各32位長。然后進行16輪完全相同的運算,這些運算被稱為函數f,在運算過程中數據與密匙結合。經過16輪后,左,右半部分合在一起經過一個末置換,完成了加密。
?
????? 在每一輪中,密匙位移位,然后再從密匙的56位中選出48位。通過一個擴展置換將數據的右半部分擴展成48位,并通過一個異或操作替代成新的32位數據,在將其置換換一次。這四步運算構成了函數f。然后,通過另一個異或運算,函數f的輸出與左半部分結合,其結果成為新的右半部分,原來的右半部分成為新的左半部分。將該操作重復16次。流程如圖2所示:
?
?
????????? 具體的算法可以參見官方文檔:http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
?
二、手機安全類介紹
???????? OPhone手機平臺上集成了若干信息安全的class,可以用來開發相關的軟件。如圖3所示。
???????? 本例采用DES算法,對通訊雙方的短信進行加解密,其他人如果沒有密鑰,將不能獲知信息內容。在本例中,用到了如下函數庫:
?
view plain copy to clipboard print ?
import?java.security.spec.KeySpec;? ?????import?javax.crypto.Cipher;?? ???????import?javax.crypto.SecretKey;??/密鑰 ??import?javax.crypto.SecretKeyFactory;?????????import?javax.crypto.spec.DESKeySpec;??? ?????
import java.security.spec.KeySpec; /*提供了加密/簽名接口 */ import javax.crypto.Cipher; /*Cipher為加密和解密提供密碼功能。它構成了 Java Cryptographic Extension (JCE) 框架的核心。 主要方法有:init:用密鑰初始化此 Cipher doFinal:按單部分操作加密或解密數據,或者結束一個多部分操作。數據將被加密或解密(具體取決于此 Cipher 的初始化方式)。 */ import javax.crypto.SecretKey; /密鑰 import javax.crypto.SecretKeyFactory; //密鑰工廠 /*密鑰工廠用來將密鑰(類型 Key 的不透明加密密鑰)轉換為密鑰規范(底層密鑰材料的透明表示形式)。秘密密鑰工廠只對秘密(對稱)密鑰進行操作。密鑰工廠為雙工模式,即其允許根據給定密鑰規范(密鑰材料)構建不透明密鑰對象,或以適當格式獲取密鑰對象的底層密鑰材料。密鑰工廠的參數包括算法 ,加密模式,填充,密碼協議 */ import javax.crypto.spec.DESKeySpec; /*實現java.security.spec.KeySpec接口,創建一個 DESKeySpec 對象。 */
三、實例編寫
3.1 xml文件
???????? 為了實現短信發送功能,需要在AndroidManifest.xml中添加permission:
view plain copy to clipboard print ?
<uses-permission?android:name="android.permission.SEND_SMS"></uses-permission>??
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
???????? 為了實現短信接收功能,除了permission之外,還需要添加receiver:
view plain copy to clipboard print ?
<receiver?android:name="DecryptoSMS"?android:enabled="true"> ??<intent-filter> ??<action?android:name="android.provider.Telephony.SMS_RECEIVED"?/> ??</intent-filter> ??</receiver>?? ????<uses-permission?android:name="android.permission.RECEIVE_SMS"></uses-permission>??
<receiver android:name="DecryptoSMS" android:enabled="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
?????? 軟件界面如圖4所示:
?????? 運行后界面如圖所示。左上角的輸入框中填寫接收端號碼,右上角的輸入框中填寫密鑰。由于DES的分塊性質,密鑰必須為8字節。SEND按鈕提供無加密的短信發送方式。
?
3.2短信生成
???????? ENCRYPT SEND按鈕提供加密短信的發送功能,該按鈕關鍵代碼如下:
view plain copy to clipboard print ?
byte?des_key[]=?enc_key.getBytes();??byte?data[]?=?new?byte[64];???byte?tempdata[]=?et_text.getText().toString().getBytes(); ????for?(int?i=0;i<tempdata.length;i++) ??????data[i]=tempdata[i]; ??if?(tempdata.length?<64){???????????for?(int?i=data.length;i<64;i++) ??????????data[i]='\0'; ??????????} ??byte?result[]?=des_crypt(des_key,?data);???
byte des_key[]= enc_key.getBytes();/*從輸入框獲取密鑰*/ byte data[] = new byte[64]; /*初始化短信數據*/ byte tempdata[]= et_text.getText().toString().getBytes(); /*從輸入框獲取短信明文*/ for (int i=0;i<tempdata.length;i++) data[i]=tempdata[i]; if (tempdata.length <64){ /*復制短信內容至data,不足64位補0*/ for (int i=data.length;i<64;i++) data[i]='\0'; } byte result[] =des_crypt(des_key, data); /*進行加密*/
3.3 加密算法
?????????? des_crypt(des_key, data)方法是利用加密密鑰和明文數據運算,獲得密文的過程。代碼如下:
?
view plain copy to clipboard print ?
static?String?DES?=?"DES/ECB/NoPadding";??? ??? ????public?static?byte[]?des_crypt(byte?key[],?byte?data[])?{?? ??????try?{?? ??????????KeySpec?ks?=?new?DESKeySpec(key);????????????SecretKeyFactory?kf?=?SecretKeyFactory.getInstance("DES");? ????? ??????????SecretKey?ky?=?kf.generateSecret(ks);????????????Cipher?c?=?Cipher.getInstance(DES);????????????c.init(Cipher.ENCRYPT_MODE,?ky);????????????return?c.doFinal(data);????????}?catch?(Exception?e)?{?? ??????????e.printStackTrace();?? ??????????return?null;?? ??????}?? ??}????
static String DES = "DES/ECB/NoPadding"; /*設置加密方式,包括算法、模式、填充的參數,具體含義參見:http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA*/ public static byte[] des_crypt(byte key[], byte data[]) { try { KeySpec ks = new DESKeySpec(key); /*新建密鑰規范*/ SecretKeyFactory kf = SecretKeyFactory.getInstance("DES"); /* 設置密鑰工廠模式為DES,可以設置為AES、DES、DESede、PBEWith等模式 http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA */ SecretKey ky = kf.generateSecret(ks); /*生成密鑰*/ Cipher c = Cipher.getInstance(DES); /*設置加密功能*/ c.init(Cipher.ENCRYPT_MODE, ky); /*加密初始化*/ return c.doFinal(data); /*加密運算*/ } catch (Exception e) { e.printStackTrace(); return null; } }
3.4 數據短信發送
?????? 獲得加密結果后,需要將數據發送出去。在之前的短信發送軟件中,用的是sendTextMessage方法,該方法只能發送文本數據。短信經過加密之后,會產生手機不能顯示的非文本字符,所以我們需要用sendDataMessage方法來發送加密數據:
view plain copy to clipboard print ?
public?final?void?sendDataMessage?(String?destinationAddress,?String?scAddress,?short?destinationPort,?byte[]?data,?PendingIntent?sentIntent,?PendingIntent?deliveryIntent)。??
public final void sendDataMessage (String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent)。
?????? 和sendTextMessage不同之處在于發送數據類型變成了byte,并且增加了目標端口號參數。
view plain copy to clipboard print ?
SmsManager?sms?=?SmsManager.getDefault();??try?{ ????short?pt=80;?????PendingIntent?pi?=?PendingIntent.getBroadcast(CryptoSMS.this,?0,?new?Intent(),?0); ????sms.sendDataMessage(et_num.getText().toString(),?null,pt,?result,?pi,?null);???Toast.makeText(CryptoSMS.this,"發送成功",Toast.LENGTH_LONG).show?(); ??}?catch?(Exception?e)?{?????? ??Toast.makeText(CryptoSMS.this,?"發送失敗\n"+e.getMessage(),Toast.?LENGTH_LONG).show(); ??}??
SmsManager sms = SmsManager.getDefault();/*建立短信發送管理對象*/ try { short pt=80; /*設置端口號*/ PendingIntent pi = PendingIntent.getBroadcast(CryptoSMS.this, 0, new Intent(), 0); sms.sendDataMessage(et_num.getText().toString(), null,pt, result, pi, null); /*填寫接收號碼、短信數據等參數,并發送短信*/ Toast.makeText(CryptoSMS.this,"發送成功",Toast.LENGTH_LONG).show (); } catch (Exception e) { Toast.makeText(CryptoSMS.this, "發送失敗\n"+e.getMessage(),Toast. LENGTH_LONG).show(); }
3.5 短信接收
?????? ?接收短信采用BroadcastReceiver實現,需要覆蓋onReceive方法。在接收到消息后,取出其中的pdu(Protocol Data Unit,協議數據單元)進行解密,獲得短信明文。
?
view plain copy to clipboard print ?
public?class?DecryptoSMS?extends?BroadcastReceiver?{ ??@Override??public?void?onReceive(Context?context,?Intent?intent)?{? ??????Bundle?bundle?=?intent.getExtras(); ??????Object?pdus[]?=?(Object[])?bundle.get("pdus");??????byte[]?tempdata?=?SmsMessage.createFromPdu((byte[])?pdus[0]).getUserData();??????String?enc_key=?"KEYabcde";?? ??????byte??des_key[]=?enc_key.getBytes(); ??????int?datalength?=?(tempdata.length?>>?3)*8;? ????????byte?data[]?=?new?byte[datalength];?? ??????for?(int?i=0;i<datalength;i++) ????????if?(i<64)?data[i]=tempdata[i];? ????????byte?result[]?=?des_decrypt(des_key,data);?? ??????String?value?=?new?String(result);????Toast.makeText(context,"Received?SMS:"+value,?Toast.LENGTH_LONG).show();??}????
public class DecryptoSMS extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object pdus[] = (Object[]) bundle.get("pdus");/*獲得pdu*/ byte[] tempdata = SmsMessage.createFromPdu((byte[]) pdus[0]).getUserData();/*轉換為byte格式*/ String enc_key= "KEYabcde"; byte des_key[]= enc_key.getBytes(); int datalength = (tempdata.length >> 3)*8; /*調整密文數據為64bit的倍數*/ byte data[] = new byte[datalength]; for (int i=0;i<datalength;i++) if (i<64) data[i]=tempdata[i]; /*為簡便起見,設置短信長度不超過64字節*/ byte result[] = des_decrypt(des_key,data); String value = new String(result); /*轉換為字符串*/ Toast.makeText(context,"Received SMS:"+value, Toast.LENGTH_LONG).show();/*提示收到明文短信*/ }
3.6 短信解密
?????? ?解密代碼僅僅在cipher的初始化參數有不同,其他完全一樣:
view plain copy to clipboard print ?
public?static?byte[]?des_decrypt(byte?key[],?byte?data[])?{?? ??????try?{?? ??????????KeySpec?ks?=?new?DESKeySpec(key);?? ??????????SecretKeyFactory?kf?=?SecretKeyFactory.getInstance("DES");?? ??????????SecretKey?ky?=?kf.generateSecret(ks);?? ??????????Cipher?c?=?Cipher.getInstance(DES);?? ??????????c.init(Cipher.DECRYPT_MODE,?ky);?? ??????????return?c.doFinal(data);?? ??????}?catch?(Exception?e)?{?? ??????????e.printStackTrace();?? ??????????return?null;?? ??????}?? ??}??
public static byte[] des_decrypt(byte key[], byte data[]) { try { KeySpec ks = new DESKeySpec(key); SecretKeyFactory kf = SecretKeyFactory.getInstance("DES"); SecretKey ky = kf.generateSecret(ks); Cipher c = Cipher.getInstance(DES); c.init(Cipher.DECRYPT_MODE, ky); return c.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } }
四、運行測試
4.1 運行環境
????? 為了在模擬器上顯示短信的收發過程,必須運行兩個模擬器。在OMS1.0的平臺上,只需在eclipse中run兩次就可以了;在OMS1.5平臺,啟動模擬器必須先創建一個 AVD( Android Virtual Device 虛擬設備 ) 。通過下列命令創建:
?
android create avd --target 1 --name myavd
?
?????? 在工程的Run configuration中(如圖5所示)配置該工程選用哪個模擬器,在圖6中,可以在指定運行的模擬器AVD上打勾。
4.2 運行結果
????????? 運行軟件后,在輸入框填寫號碼、密鑰、短信明文,點擊ENCRYPT SEND,稍后在另外一個模擬器就能收到密文和明文,如圖7所示。可以看到,在收件箱中收到的是亂碼,但是在Toast中顯示的是解密的結果。
五、總結
??????? 本文介紹了用DES算法加密短信的辦法,簡單實用。
?
??????? DES由于其算法簡單,可以在幾天內被攻破,現在正在逐漸淡出加密舞臺。但是,3重DES(triple-DES)還是具有很強的保密性和實用性,其官方文檔鏈接地址如下:http://webstore.ansi.org/RecordDetail.aspx?sku=ANSI+X9.52%3a1998 用戶可以通過在DES的基礎上略微修改實現。另外,AES(Advanced Encryption Standard)算法的安全性大大超過了DES,當前具有很廣的應用。在Cipher的參數中可以選擇AES算法來提高安全性,
??????? 但是和三重DES一樣,用戶需要犧牲運算時間。值得注意的是AES的明文分塊是128bit的,密鑰是128/192/256bit的,需要在代碼中修改byte數組的長度來實現。
?
參考文獻
【1】《應用密碼學--協議、算法與C源程序》,譯者: 吳世忠等,作者: (美)旋奈爾(Schneier,B.)
【2】對稱算法(一)DES算法,http://www.infosecurity.org.cn/article/pki/cryptography/23407.html
?
作者介紹
?????? 周軒,就職于浙江移動,OPhone SDN入門版版主,北郵通信碩士,擅長嵌入式系統底層開發,關注移動互聯網的發展。
?
(聲明:本網的新聞及文章版權均屬OPhone SDN網站所有,如需轉載請與我們編輯團隊聯系。任何媒體、網站或個人未經本網書面協議授權,不得進行任何形式的轉載。已經取得本網協議授權的媒體、網站,在轉載使用時請注明稿件來源。)
總結
以上是生活随笔為你收集整理的手机的短信加解密的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。