#
這到底是怎樣一個(gè)問題呢?還是用例子說明吧:
public class Parameter{
static void aMethod(){
int a=1; //定義一個(gè)int a
change(a);
System.out.println(a);
}
static void change(int a){ //將傳入的a加1
a++;
}
public static void main(String[] args){
aMethod(); //執(zhí)行并輸出
}
}
猜猜程序的輸出會(huì)是什么呢?1還是2?結(jié)果是1。為什么呢?
因?yàn)閍是int 數(shù)據(jù),所以作為參數(shù)傳遞的時(shí)候,a并沒真正傳入change(a).傳入的是a的一個(gè)副本。所以change不管怎么對(duì)a進(jìn)行處理都不會(huì)改變aMethod中a的值。
那么有沒有辦法通過外部的一個(gè)方法改變另一個(gè)方法里的值呢?當(dāng)然有,只要使用對(duì)象的引用也叫句柄。說起來文縐縐的倒不如舉個(gè)例子:
import java.util.*; //LinkedList要用到這個(gè)包
public class Parameter{
static void aMethod(){
LinkedList a = new LinkedList(); //生成一個(gè)LinkedList a對(duì)象
a.add("a");
change(a);
for(int i=0;i<a.size();i++){ //將鏈表中所有數(shù)據(jù)輸出
System.out.println(a.get(i).toString());
}
}
static void change(LinkedList a){ //將傳入的a加1
a.add("b"); //為a中再添加一個(gè)b
}
public static void main(String[] args){
aMethod(); //執(zhí)行并輸出
}
}
輸出的結(jié)果是:
a
b
這說明了什么?說明change(LinkedList a)方法已經(jīng)改變了a中的值。那么為什么a是對(duì)象就可以改變呢?我們將a傳入change方法的時(shí)候傳入的不是某個(gè)對(duì)象,而是這個(gè)對(duì)象的引用(或者叫做句柄)插入一句,什么是句柄?比如你,作為一個(gè)人,是一個(gè)對(duì)象,引用(句柄)就是你的身份證號(hào)碼。當(dāng)我們把引用作為參數(shù)傳入方法的時(shí)候,引用同樣也進(jìn)行了復(fù)制,但復(fù)制后的引用指向同一個(gè)對(duì)象,所以change()里對(duì)a 的改變其實(shí)也就是對(duì)aMethod()里a的改變,因?yàn)樗麄兪峭粋€(gè)對(duì)象!
是不是說只要是對(duì)象就可以了呢?不一定!
比如String類型的數(shù)據(jù),即使你這樣生成一個(gè)String a對(duì)象
String a = new String("go to hell");
a的確是一個(gè)對(duì)象,但是在a的引用復(fù)制的時(shí)候,原來的對(duì)象也會(huì)丟失。其實(shí)String 類型的數(shù)據(jù)在每次改變應(yīng)用的時(shí)候都會(huì)清楚原來的對(duì)象。
比如在你這么使用的時(shí)候:
String a="you";//第一行
a=a+"are fool";//第二行
第一行的a和第二行的a所代表的是完全不同的對(duì)象。所以說如果程序里要對(duì)String進(jìn)行大量改變的時(shí)候建議不要使用String,如果不小心使用了,你的程序?qū)⒛涿畹卣加么罅康膬?nèi)存。不用String用什么?用StringBuffer!
不想說得太過于文縐縐,其實(shí)序列化,說白了就是將對(duì)象以文件的形式保存起來,反序列化,顧名思義,就是將對(duì)象文件轉(zhuǎn)化為程序中的對(duì)象。一個(gè)對(duì)象如果要被序列化則必須實(shí)現(xiàn)Serializable接口(implements Serializable)。
序列化:
在這一過程中需要用到j(luò)ava.io包中的地兩個(gè)類:FileOutputSteam 和ObjectOutputSteam
下面是一個(gè)將LinkedList對(duì)象序列化的簡(jiǎn)單例子,LinkedList已經(jīng)實(shí)現(xiàn)了Serializable接口(implements Serializable),方法(Method)如下:
import java.io.*;
...//外部代碼
public static void OutputObject() throws
FileNotFoundException,IOException{
LinkedList ll=new LinkedList();
FileOutputStream fos=new FileOutputStream("object");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(ll);
}
...//外部代碼
關(guān)鍵代碼就是三行,相當(dāng)容易。
反序列化:
這一過程要用到FileInputStream和ObjectInputSteam,都在java.io包里
...//外部代碼
public static Object InputObject() throws FileNotFoundException,
IOException, ClassNotFoundException{
FileInputStream fis=new FileInputStream("object");
ObjectInputStream ois=new ObjectInputStream(fis);
return ois.readObject();//返回對(duì)象
}
...//外部代碼
關(guān)鍵代碼就是兩行。
當(dāng)然這只是一個(gè)簡(jiǎn)單的入門,如果你被老外的書整暈了的話,上面這兩段代碼是很好的參考。
在java中,我們可以通過兩種方式來獲取隨機(jī)數(shù)(generating a random number)一種是大家熟悉的java.lang.Math.Random()靜態(tài)方法,另一種是創(chuàng)建java.util.Random對(duì)象。下面是兩種方法的使用過程:
一.java.lang.Math.random()
在使用這一靜態(tài)方法的時(shí)候,我們不需要import任何包,因?yàn)閖ava.lang.*包是默認(rèn)載入的,下面舉例說面使用方法:
public class RandomTest{
public static void main(String[] args){
int i=Math.random();//random()會(huì)自動(dòng)產(chǎn)生一個(gè)0.0-1.0的雙精度隨機(jī)數(shù)
System.out.println(i);//輸出
i=Math.random()*1000;//產(chǎn)生0-1000的雙精度隨機(jī)數(shù)
System.out.println(i);
int b=(int)(Math.random()*1000);//產(chǎn)生0-1000的整數(shù)隨機(jī)數(shù)
System.out.println(b);
}
}
二.創(chuàng)建java.util.Random對(duì)象
import java.util.random
public class RandomTest{
public static void main(String[] args){
Random random=new Random();//創(chuàng)建random對(duì)象
int intNumber=random.nextInt();//獲取一個(gè)整型數(shù)
float floatNumber=random.nextFloat();//獲取一個(gè)浮點(diǎn)數(shù)(0-1)
double doubleNumber=random.nextDouble();//獲取雙精度數(shù)(0-1)
boolean booleanNumber=random.nextBoolean();//獲取boolean數(shù)
System.out.println("intNumber:"+intNumber);
System.out.println("floatNumber:"+floatNumber);
System.out.println("doubleNumber:"+doubleNumber);
System.out.println("booleanNumber:"+booleanNumber);
}
}
random在產(chǎn)生隨機(jī)數(shù)的時(shí)候使用當(dāng)前的時(shí)間作為基數(shù),我們可以同過System.currentTimeMillis()來獲取這個(gè)基數(shù)。當(dāng)然我們也可以指定基數(shù):
Random random=new Random(100);
同一基數(shù)所產(chǎn)生的隨機(jī)數(shù)序列是一樣的,可以用下面這一段程序進(jìn)行印證:
import java.util.random
public class RandomTest{
public static void main(String[] args){
Random random1=new Random(100);
Random random2=new Random(100);
for(int i=0;i<5;i++){
System.out.print(random1.nextInt()+"\t");
System.out.println(random2.nextInt()+"\t");
System.out.println("---------------------------------");
}
}
}
我們可以發(fā)現(xiàn)random1和random2所產(chǎn)生的隨機(jī)數(shù)是相同的。
根據(jù)約定,在使用java編程的時(shí)候應(yīng)盡可能的使用現(xiàn)有的類庫,當(dāng)然你也可以自己編寫一個(gè)排序的方法,或者框架,但是有幾個(gè)人能寫得比JDK里的還要好呢?使用現(xiàn)有的類的另一個(gè)好處是代碼易于閱讀和維護(hù),這篇文章主要講的是如何使用現(xiàn)有的類庫對(duì)數(shù)組和各種Collection容器進(jìn)行排序,(文章中的一部分例子來自《Java Developers Almanac 1.4》)
首先要知道兩個(gè)類:java.util.Arrays和java.util.Collections(注意和Collection的區(qū)別)Collection是集合框架的頂層接口,而Collections是包含了許多靜態(tài)方法。我們使用Arrays對(duì)數(shù)組進(jìn)行排序,使用 Collections對(duì)結(jié)合框架容器進(jìn)行排序,如ArraysList,LinkedList等。
例子中都要加上import java.util.*和其他外殼代碼,如類和靜態(tài)main方法,我會(huì)在第一個(gè)例子里寫出全部代碼,接下來會(huì)無一例外的省略。
對(duì)數(shù)組進(jìn)行排序
比如有一個(gè)整型數(shù)組:
int[] intArray = new int[] {4, 1, 3, -23};
我們?nèi)绾芜M(jìn)行排序呢?你這個(gè)時(shí)候是否在想快速排序的算法?看看下面的實(shí)現(xiàn)方法:
import java.util.*;
public class Sort{
public static void main(String[] args){
int[] intArray = new int[] {4, 1, 3, -23};
Arrays.sort(intArray);
}
}
這樣我們就用Arrays的靜態(tài)方法sort()對(duì)intArray進(jìn)行了升序排序,現(xiàn)在數(shù)組已經(jīng)變成了{(lán)-23,1,3,4}.
如果是字符數(shù)組:
String[] strArray = new String[] {"z", "a", "C"};
我們用:
Arrays.sort(strArray);
進(jìn)行排序后的結(jié)果是{C,a,z},sort()會(huì)根據(jù)元素的自然順序進(jìn)行升序排序。如果希望對(duì)大小寫不敏感的話可以這樣寫:
Arrays.sort(strArray, String.CASE_INSENSITIVE_ORDER);
當(dāng)然我們也可以指定數(shù)組的某一段進(jìn)行排序比如我們要對(duì)數(shù)組下表0-2的部分(假設(shè)數(shù)組長(zhǎng)度大于3)進(jìn)行排序,其他部分保持不變,我們可以使用:
Arrays.sort(strArray,0,2);
這樣,我們只對(duì)前三個(gè)元素進(jìn)行了排序,而不會(huì)影響到后面的部分。
當(dāng)然有人會(huì)想,我怎樣進(jìn)行降序排序?在眾多的sort方法中有一個(gè)
我們使用Comparator獲取一個(gè)反序的比較器即可,Comparator會(huì)在稍后講解,以前面的intArray[]為例:
Arrays.sort(intArray,Comparator.reverseOrder());
這樣,我們得到的結(jié)果就是{4,3,1,-23}。如果不想修改原有代碼我們也可以使用:
Collections.reverse(Arrays.asList(intArray));
得到該數(shù)組的反序。結(jié)果同樣為4,3,1,-23}。
現(xiàn)在的情況變了,我們的數(shù)組里不再是基本數(shù)據(jù)類型(primtive type)或者String類型的數(shù)組,而是對(duì)象數(shù)組。這個(gè)數(shù)組的自然順序是未知的,因此我們需要為該類實(shí)現(xiàn)Comparable接口,比如我們有一個(gè)Name類:
class Name implements Comparable<Name>{
public String firstName,lastName;
public Name(String firstName,String lastName){
this.firstName=firstName;
this.lastName=lastName;
}
public int compareTo(Name o) { //實(shí)現(xiàn)接口
int lastCmp=lastName.compareTo(o.lastName);
return (lastCmp!=0?lastCmp:firstName.compareTo(o.firstName));
}
public String toString(){ //便于輸出測(cè)試
return firstName+" "+lastName;
}
}
這樣,當(dāng)我們對(duì)這個(gè)對(duì)象數(shù)組進(jìn)行排序時(shí),就會(huì)先比較lastName,然后比較firstName 然后得出兩個(gè)對(duì)象的先后順序,就像compareTo(Name o)里實(shí)現(xiàn)的那樣。不妨用程序試一試:
import java.util.*;
public class NameSort {
public static void main(String[] args) {
Name nameArray[] = {
new Name("John", "Lennon"),
new Name("Karl", "Marx"),
new Name("Groucho", "Marx"),
new Name("Oscar", "Grouch")
};
Arrays.sort(nameArray);
for(int i=0;i<nameArray.length;i++){
System.out.println(nameArray[i].toString());
}
}
}
結(jié)果正如我們所愿:
Oscar Grouch
John Lennon
Groucho Marx
Karl Marx
對(duì)集合框架進(jìn)行排序
如果已經(jīng)理解了Arrays.sort()對(duì)數(shù)組進(jìn)行排序的話,集合框架的使用也是大同小異。只是將Arrays替換成了Collections,注意Collections是一個(gè)類而Collection是一個(gè)接口,雖然只差一個(gè)"s"但是它們的含義卻完全不同。
假如有這樣一個(gè)鏈表:
LinkedList list=new LinkedList();
list.add(4);
list.add(34);
list.add(22);
list.add(2);
我們只需要使用:
Collections.sort(list);
就可以將ll里的元素按從小到大的順序進(jìn)行排序,結(jié)果就成了:
[2, 4, 22, 34]
如果LinkedList里面的元素是String,同樣會(huì)想基本數(shù)據(jù)類型一樣從小到大排序。
如果要實(shí)現(xiàn)反序排序也就是從達(dá)到小排序:
Collections.sort(list,Collectons.reverseOrder());
如果LinkedList里面的元素是自定義的對(duì)象,可以像上面的Name對(duì)象一樣實(shí)現(xiàn)Comparable接口,就可以讓Collection.sort()為您排序了。
如果你想按照自己的想法對(duì)一個(gè)對(duì)象進(jìn)行排序,你可以使用
這個(gè)方法進(jìn)行排序,在給出例子之前,先要說明一下Comparator的使用,
Comparable接口的格式:
public interface Comparator<T> {
int compare(T o1, T o2);
}
其實(shí)Comparator里的int compare(T o1,T o2)的寫法和Comparable里的compareTo()方法的寫法差不多。在上面的Name類中我們的比較是從LastName開始的,這是西方人的習(xí)慣,到了中國,我們想從fristName開始比較,又不想修改原來的代碼,這個(gè)時(shí)候,Comparator就可以派上用場(chǎng)了:
final Comparator<Name> FIRST_NAME_ORDER=new Comparator<Name>() {
public int compare(Name n1, Name n2) {
int firstCmp=n1.firstName.compareTo(n2.firstName);
return (firstCmp!=0?firstCmp:n1.lastName.compareTo
(n2.firstName));
}
};
這樣一個(gè)我們自定義的Comparator FIRST_NAME_ORDER就寫好了。
將上個(gè)例子里那個(gè)名字?jǐn)?shù)組轉(zhuǎn)化為L(zhǎng)ist:
List<Name> list=Arrays.asList(nameArray);
Collections.sort(list,FIRST_NAME_ORDER);
這樣我們就成功的使用自己定義的比較器設(shè)定排序。
在openssl或其他密碼相關(guān)的資料中,我們經(jīng)常看到對(duì)稱加密算法有ECB、CBC之類加密模式的簡(jiǎn)稱,到底這些加密模式是什么呢?它們之間有什么不同呢,今天就是為大家解開這個(gè)迷。
在現(xiàn)有的對(duì)稱加密算法中,主要有4種加密處理模式,這4種加密處理模式一般是針對(duì)塊加密算法而言的,如DES算法。這4種加密模式羅列如下:
模式中文描述 英文名稱(Openssl縮寫)
電子密碼本模式 Electronic Code Book(ECB)
加密塊鏈模式 Cipher Block Chaining(CBC)
加密反饋模式 Cipher Feedback Mode(CFB)
輸出反饋模式 Output Feedback Mode(OFB)
下面我們分別介紹這4種加密模式。
**********************************************************************
【電子密碼本模式】
這種模式是最早采用和最簡(jiǎn)單的模式,它將加密的數(shù)據(jù)分成若干組,每組的大小跟加密密鑰長(zhǎng)度相同,然后每組都用相同的密鑰進(jìn)行加密。比如DES算法,一個(gè)64位的密鑰,如果采用該模式加密,就是將要加密的數(shù)據(jù)分成每組64位的數(shù)據(jù),如果最后一組不夠64位,那么就補(bǔ)齊為64位,然后每組數(shù)據(jù)都采用DES算法的64位密鑰進(jìn)行加密。下圖:
_______________________
My name |is Drago|nKing
-----------------------
上圖“My name is DragonKing”這句話每8個(gè)字符(64位)作為一塊,然后使用一個(gè)相同的64位的密鑰對(duì)每個(gè)塊進(jìn)行加密,最后一塊不足64位,就補(bǔ)齊后再進(jìn)行加密。
可以看到,因?yàn)镋CB方式每64位使用的密鑰都是相同的,所以非常容易獲得密文進(jìn)行密碼破解,此外,因?yàn)槊?4位是相互獨(dú)立的,有時(shí)候甚至不用破解密碼,只要簡(jiǎn)單的將其中一塊替換就可以達(dá)到黑客目的。
【加密塊鏈模式】
從這兩個(gè)圖中大家可以看到,CBC模式的加密首先也是將明文分成固定長(zhǎng)度(64位)的塊(P0,P1...),然后將前面一個(gè)加密塊輸出的密文與下一個(gè)要加密的明文塊進(jìn)行XOR(異或)操作計(jì)算,將計(jì)算結(jié)果再用密鑰進(jìn)行加密得到密文。第一明文塊加密的時(shí)候,因?yàn)榍懊鏇]有加密的密文,所以需要一個(gè)初始化向量(IV)。跟ECB方式不一樣,通過連接關(guān)系,使得密文跟明文不再是一一對(duì)應(yīng)的關(guān)系,破解起來更困難,而且克服了只要簡(jiǎn)單調(diào)換密文塊可能達(dá)到目的的攻擊。
但是該加密模式的缺點(diǎn)是不能實(shí)時(shí)解密,也就是說,必須等到每8個(gè)字節(jié)都接受到之后才能開始加密,否則就不能得到正確的結(jié)果。這在要求實(shí)時(shí)性比較高的時(shí)候就顯得不合適了。所以才有了下面兩種加密模式。
【加密反饋模式】
加密反饋模式為了克服必須等待8個(gè)字節(jié)全部得到才能進(jìn)行解密的缺點(diǎn),采用了一個(gè)64位(8個(gè)字節(jié))的位移寄存器來獲得密文,如下圖所示:
上面兩個(gè)圖中C2、C3以及P10等都是一個(gè)字節(jié)(8位)的數(shù)據(jù),所以能夠?qū)崿F(xiàn)字符的實(shí)時(shí)加密和解密,不用再等到8個(gè)字節(jié)都接受到之后再進(jìn)行解密。圖示是在進(jìn)行第10個(gè)字節(jié)數(shù)據(jù)的加密和解密過程,在該過程中,先從移位寄存器取8個(gè)字節(jié)的數(shù)據(jù)(C2到C9)用密鑰進(jìn)行加密,然后取加密數(shù)據(jù)最左邊的一個(gè)字節(jié)跟輸入的明文P10進(jìn)行XOR(異或)操作,得到的值作為輸出密文C10,同時(shí)將C10送入到移位寄存器中。
需要注意的是,如果其中有一個(gè)字節(jié)的密文在傳輸?shù)臅r(shí)候發(fā)生錯(cuò)誤(即使是其中的一位),那么它出現(xiàn)在移位寄存器期間解密的8個(gè)字節(jié)的數(shù)據(jù)都會(huì)得不到正確的解密結(jié)果,當(dāng)然,這8個(gè)字節(jié)過去之后,依然可以得到正確的解密結(jié)果。但是一個(gè)比特錯(cuò)誤就影響到8個(gè)字節(jié)(64個(gè)比特)的正確結(jié)果,導(dǎo)致魯棒性太差,所以就又提出了下面的加密模式OFB。
【輸出反饋模式】
輸出反饋模式OFB跟CFB幾乎是一樣的,除了其以為寄存器的輸入數(shù)據(jù)稍微有一點(diǎn)不同之外,如下圖:
可以看到,這種方法因?yàn)闆]有采用密文作為加密的數(shù)據(jù),所以克服了由于傳輸過程中由于單個(gè)比特導(dǎo)致64個(gè)相關(guān)比特解密失敗的情況,在本模式下,如果一個(gè)比特發(fā)生錯(cuò)誤了,那么只會(huì)影響其本身對(duì)應(yīng)的一個(gè)比特,而不會(huì)影響別的。但是相對(duì)于其它模式,因?yàn)閿?shù)據(jù)之間相關(guān)性小,這種加密模式是比較不安全的,所以在應(yīng)用的時(shí)候除非特別需要,一般不提倡應(yīng)用OFB模式。
原文地址 http://hi.baidu.com/msingle/blog/item/e9d7cd455e02ed25cffca3a6.html
其他的一些補(bǔ)充:
■ 縮寫說明 ■
IN - 輸入向量
OUT - 輸出向量(未用于和明文加密前)
ENC - 加密算法
K - 加密密鑰
P - 明文
C - 密文
XOR - 異或
<< - 左移
BSIZE - 算法的加密塊尺寸
COUNT - 計(jì)數(shù)器
------------------------------------------------------------------------------
計(jì)數(shù)器(CTR)模式: IN(N) = ENC(K, COUNT++), C(N) = IN(N) XOR P(N);CTR 模式被廣泛用于 ATM 網(wǎng)絡(luò)安全和 IPSec應(yīng)用中,相對(duì)于其它模式而言,CRT模式具有如下特點(diǎn):
■ 硬件效率:允許同時(shí)處理多塊明文 / 密文。
■ 軟件效率:允許并行計(jì)算,可以很好地利用 CPU 流水等并行技術(shù)。
■ 預(yù)處理: 算法和加密盒的輸出不依靠明文和密文的輸入,因此如果有足夠的保證安全的存儲(chǔ)器,加密算法將僅僅是一系列異或運(yùn)算,這將極大地提高吞吐量。
■ 隨機(jī)訪問:第 i 塊密文的解密不依賴于第 i-1 塊密文,提供很高的隨機(jī)訪問能力
■ 可證明的安全性:能夠證明 CTR 至少和其他模式一樣安全(CBC, CFB, OFB, ...)
■ 簡(jiǎn)單性:與其它模式不同,CTR模式僅要求實(shí)現(xiàn)加密算法,但不要求實(shí)現(xiàn)解密算法。對(duì)于 AES 等加/解密本質(zhì)上不同的算法來說,這種簡(jiǎn)化是巨大的。
■ 無填充,可以高效地作為流式加密使用。
------------------------------------------------------------------------------
密文塊鏈接(CBC)模式:IN(N) = P(N) XOR C(N-1), C(N) = ENC(K, IN(N));在 CTR出現(xiàn)前廣泛使用的塊加密模式,用于安全的分組(迭代式)加密和認(rèn)證。
------------------------------------------------------------------------------
密文反饋 (CFB) 模式: IN(N) = C(N-1) << (BSIZE-j), C(N) = ENC(K, IN(N)) << (BSIZE-j) XOR P(N). 其中 j 為每次加密的位數(shù)。CFB 模式與 CBC 模式原理相似,但一次僅處理 j 位數(shù)據(jù),其余 BLOCKSIZE - j 位丟棄。由于以上性質(zhì),CFB 模式可以在不損失安全性的前提下,將塊加密變?yōu)榱魇郊用堋5窃撃J揭彩潜容^浪費(fèi)的,因?yàn)樵诿枯喖咏饷苤卸紒G棄了大部分結(jié)果(j 通常為一字節(jié)(8 位),塊加密算法中每塊的尺寸通常為64、128 或 256 位不等)。
------------------------------------------------------------------------------
輸出反饋 (OFB) 模式:IN(N) = OUT(N-1) << (BSIZE-j), C(N) = ENC(K, IN(N)) << (BSIZE-j) XOR P(N), OUT(N) = ENC(K, IN(N)) << (BSIZE-j). 該模式與 CFB 模式基本相同,只不過本次輸入是上次迭代中尚未與明文異或時(shí)的輸出。 與 CFB 模式一樣, OFB 模式也可以作為流加密模式使用,除此之外,由于每次迭代的輸入不是上次迭代的密文,從而保證了較強(qiáng)的容錯(cuò)能力, 即: 對(duì)一塊(一字節(jié))密文的傳輸錯(cuò)誤不會(huì)影響到后繼密文。但是,由于輸入沒有經(jīng)過密文疊加使得其抗篡改攻擊的能力較差,通常需要與消息驗(yàn)
證算法或數(shù)字簽名算法配套使用。OFB 通常用于噪音水平較高的通信連接以及一般的流式應(yīng)用中。
------------------------------------------------------------------------------
電碼本(ECB)模式: IN(N) = P(N), C(N) = ENC(K, IN(N)). 最簡(jiǎn)單但最不安全的加密方式。每次迭代的輸入都使用相同密鑰進(jìn)行無變換的直接加密。對(duì)于同樣的明文片斷,總會(huì)產(chǎn)生相同的,與之對(duì)應(yīng)的密文段。抗重復(fù)統(tǒng)計(jì)和結(jié)構(gòu)化分析的能力較差。一次性加密的最壞情況 (即:每次輸入的明文都小于等于 BSIZE 時(shí)) 就是電碼本模式。 僅在一次一密,或傳出極少數(shù)據(jù)時(shí)考慮使用 ECB 模式。
轉(zhuǎn)自:IaWeN's Blog-iawen,原創(chuàng),安全,破解視頻,網(wǎng)頁設(shè)計(jì),影視后期,AE特效
鏈接:http://www.iawen.com/read.php?296
形參出現(xiàn)在函數(shù)定義中,在整個(gè)函數(shù)體內(nèi)都可以使用, 離開該函數(shù)則不能使用。
實(shí)參出現(xiàn)在主調(diào)函數(shù)中,進(jìn)入被調(diào)函數(shù)后,實(shí)參變量也不能使用。
形參和實(shí)參的功能是作數(shù)據(jù)傳送。發(fā)生函數(shù)調(diào)用時(shí), 主調(diào)函數(shù)把實(shí)參的值傳送給被調(diào)函數(shù)的形參從而實(shí)現(xiàn)主調(diào)函數(shù)向被調(diào)函數(shù)的數(shù)據(jù)傳送。
1.形參變量只有在被調(diào)用時(shí)才分配內(nèi)存單元,在調(diào)用結(jié)束時(shí), 即刻釋放所分配的內(nèi)存單元。因此,形參只有在函數(shù)內(nèi)部有效。 函數(shù)調(diào)用結(jié)束返回主調(diào)函數(shù)后則不能再使用該形參變量。
2.實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等, 無論實(shí)參是何種類型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應(yīng)預(yù)先用賦值,輸入等辦法使實(shí)參獲得確定值。
3.實(shí)參和形參在數(shù)量上,類型上,順序上應(yīng)嚴(yán)格一致, 否則會(huì)發(fā)生“類型不匹配”的錯(cuò)誤。
4.函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳送是單向的。 即只能把實(shí)參的值傳送給形參,而不能把形參的值反向地傳送給實(shí)參。 因此在函數(shù)調(diào)用過程中,形參的值發(fā)生改變,而實(shí)參中的值不會(huì)變化。
5.當(dāng)形參和實(shí)參不是指針類型時(shí),在該函數(shù)運(yùn)行時(shí),形參和實(shí)參是不同的變量,他們?cè)趦?nèi)存中位于不同的位置,形參將實(shí)參的內(nèi)容復(fù)制一份,在該函數(shù)運(yùn)行結(jié)束的時(shí)候形參被釋放,而實(shí)參內(nèi)容不會(huì)改變。 而如果函數(shù)的參數(shù)是指針類型變量,在調(diào)用該函數(shù)的過程中,傳給函數(shù)的是實(shí)參的地址,在函數(shù)體內(nèi)部使用的也是實(shí)參的地址,即使用的就是實(shí)參本身。所以在函數(shù)體內(nèi)部可以改變實(shí)參的值
什么是對(duì)稱加密技術(shù)?
對(duì)稱加密采用了對(duì)稱密碼編碼技術(shù),它的特點(diǎn)是文件加密和解密使用相同的密鑰,即加密密鑰也可以用作解密密鑰,這種方法在密碼學(xué)中叫做對(duì)稱加密算法,對(duì)稱加密算法使用起來簡(jiǎn)單快捷,密鑰較短,且破譯困難,除了數(shù)據(jù)加密標(biāo)準(zhǔn)(DES),另一個(gè)對(duì)稱密鑰加密系統(tǒng)是國際數(shù)據(jù)加密算法(IDEA),它比DES的加密性好,而且對(duì)計(jì)算機(jī)功能要求也沒有那么高。IDEA加密標(biāo)準(zhǔn)由PGP(Pretty Good Privacy)系統(tǒng)使用。
對(duì)稱加密算法在電子商務(wù)交易過程中存在幾個(gè)問題:
1、要求提供一條安全的渠道使通訊雙方在首次通訊時(shí)協(xié)商一個(gè)共同的密鑰。直接的面對(duì)面協(xié)商可能是不現(xiàn)實(shí)而且難于實(shí)施的,所以雙方可能需要借助于郵件和電話等其它相對(duì)不夠安全的手段來進(jìn)行協(xié)商;
2、密鑰的數(shù)目難于管理。因?yàn)閷?duì)于每一個(gè)合作者都需要使用不同的密鑰,很難適應(yīng)開放社會(huì)中大量的信息交流;
3、對(duì)稱加密算法一般不能提供信息完整性的鑒別。它無法驗(yàn)證發(fā)送者和接受者的身份;
4、對(duì)稱密鑰的管理和分發(fā)工作是一件具有潛在危險(xiǎn)的和煩瑣的過程。對(duì)稱加密是基于共同保守秘密來實(shí)現(xiàn)的,采用對(duì)稱加密技術(shù)的貿(mào)易雙方必須保證采用的是相同的密鑰,保證彼此密鑰的交換是安全可靠的,同時(shí)還要設(shè)定防止密鑰泄密和更改密鑰的程序。
假設(shè)兩個(gè)用戶需要使用對(duì)稱加密方法加密然后交換數(shù)據(jù),則用戶最少需要2個(gè)密鑰并交換使用,如果企業(yè)內(nèi)用戶有n個(gè),則整個(gè)企業(yè)共需要n×(n-1) 個(gè)密鑰,密鑰的生成和分發(fā)將成為企業(yè)信息部門的惡夢(mèng)。
常見的對(duì)稱加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES
什么是非對(duì)稱加密技術(shù)
1976年,美國學(xué)者Dime和Henman為解決信息公開傳送和密鑰管理問題,提出一種新的密鑰交換協(xié)議,允許在不安全的媒體上的通訊雙方交換信息,安全地達(dá)成一致的密鑰,這就是“公開密鑰系統(tǒng)”。相對(duì)于“對(duì)稱加密算法”這種方法也叫做“非對(duì)稱加密算法”。
與對(duì)稱加密算法不同,非對(duì)稱加密算法需要兩個(gè)密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對(duì),如果用公開密鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私有密鑰才能解密;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密,那么只有用對(duì)應(yīng)的公開密鑰才能解密。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,所以這種算法叫作非對(duì)稱加密算法。
非對(duì)稱加密算法實(shí)現(xiàn)機(jī)密信息交換的基本過程是:甲方生成一對(duì)密鑰并將其中的一把作為公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對(duì)加密后的信息進(jìn)行解密。甲方只能用其專用密鑰解密由其公用密鑰加密后的任何信息。
非對(duì)稱加密算法的保密性比較好,它消除了最終用戶交換密鑰的需要,但加密和解密花費(fèi)時(shí)間長(zhǎng)、速度慢,它不適合于對(duì)文件加密而只適用于對(duì)少量數(shù)據(jù)進(jìn)行加密。
如果企業(yè)中有n個(gè)用戶,企業(yè)需要生成n對(duì)密鑰,并分發(fā)n個(gè)公鑰。由于公鑰是可以公開的,用戶只要保管好自己的私鑰即可(企業(yè)分發(fā)后一般保存的是私鑰,用戶拿的是公鑰),因此加密密鑰的分發(fā)將變得十分簡(jiǎn)單。同時(shí),由于每個(gè)用戶的私鑰是唯一的,其他用戶除了可以可以通過信息發(fā)送者的公鑰來驗(yàn)證信息的來源是否真實(shí),還可以確保發(fā)送者無法否認(rèn)曾發(fā)送過該信息。非對(duì)稱加密的缺點(diǎn)是加解密速度要遠(yuǎn)遠(yuǎn)慢于對(duì)稱加密,在某些極端情況下,甚至能比非對(duì)稱加密慢上1000倍。
非對(duì)稱加密的典型應(yīng)用是數(shù)字簽名。
常見的非對(duì)稱加密算法有:RSA、ECC(移動(dòng)設(shè)備用)、Diffie-Hellman、El Gamal、DSA(數(shù)字簽名用)
企業(yè)加密系統(tǒng)應(yīng)用 常用加密算法介紹
對(duì)稱加密、非對(duì)稱加密、hash加密(md5加密是典型應(yīng)用)
Hash算法
Hash算法特別的地方在于它是一種單向算法,用戶可以通過Hash算法對(duì)目標(biāo)信息生成一段特定長(zhǎng)度的唯一的Hash值,卻不能通過這個(gè)Hash值重新獲得目標(biāo)信息。因此Hash算法常用在不可還原的密碼存儲(chǔ)、信息完整性校驗(yàn)等。
常見的Hash算法有MD2、MD4、MD5、HAVAL、SHA
加密算法的效能通常可以按照算法本身的復(fù)雜程度、密鑰長(zhǎng)度(密鑰越長(zhǎng)越安全)、加解密速度等來衡量。上述的算法中,除了DES密鑰長(zhǎng)度不夠、MD2速度較慢已逐漸被淘汰外,其他算法仍在目前的加密系統(tǒng)產(chǎn)品中使用。
對(duì)于較長(zhǎng)的明文進(jìn)行加密需要進(jìn)行分塊加密,但是直接加密(ecb)不容易隱藏模式,用OpenCV寫了個(gè)程序論證了一下
ECB
優(yōu)點(diǎn)就是簡(jiǎn)單,可以并行計(jì)算,不會(huì)迭代誤差
缺點(diǎn)就是隱藏不了模式

CBC
需要初始化向量IV,來加密第一塊C0.
有點(diǎn)就是比ECB好
缺點(diǎn)不利于并行計(jì)算、誤差會(huì)迭代,還需要初始向量


加密算法為簡(jiǎn)單的位翻轉(zhuǎn)
- #define bitrev(b) (((b)<<7)&0x80) | \
- (((b)<<5)&0x40) | \
- (((b)<<3)&0x20) | \
- (((b)<<1)&0x10) | \
- (((b)>>1)&0x08) | \
- (((b)>>3)&0x04) | \
- (((b)>>5)&0x02) | \
- (((b)>>7)&0x01)
#define bitrev(b) (((b)<<7)&0x80) | \
(((b)<<5)&0x40) | \
(((b)<<3)&0x20) | \
(((b)<<1)&0x10) | \
(((b)>>1)&0x08) | \
(((b)>>3)&0x04) | \
(((b)>>5)&0x02) | \
(((b)>>7)&0x01)
ECB加密,就是直接分塊進(jìn)行加密
- for(int i=0;i<grey->width;i++)
- for(int j=0;j<grey->height;j++)
- grey->imageData[j*grey->width+i]=bitrev(grey->imageData[j*grey->width+i]);
- cvNamedWindow("ecb");
- cvShowImage("ecb", grey);
for(int i=0;i<grey->width;i++)
for(int j=0;j<grey->height;j++)
grey->imageData[j*grey->width+i]=bitrev(grey->imageData[j*grey->width+i]);
cvNamedWindow("ecb");
cvShowImage("ecb", grey);
CBC加密,與上一塊密文異或后加密
- for(int i=0;i<grey->width;i++)
- for(int j=0;j<grey->height;j++)
- if(i!=0&&j!=0)
- grey->imageData[j*grey->width+i]=bitrev(grey->imageData[j*grey->width+i]^grey->imageData[j*grey->width+i-1]);
- else
- grey->imageData[0]=grey->imageData[0]^IV;
- cvNamedWindow("cbc");
- cvShowImage("cbc", grey);
一. AES對(duì)稱加密:

AES加密

分組
二. 分組密碼的填充

分組密碼的填充
e.g.:

三. 流密碼:

四. 分組密碼加密中的四種模式:
3.1 ECB模式

優(yōu)點(diǎn):
1.簡(jiǎn)單;
2.有利于并行計(jì)算;
3.誤差不會(huì)被傳送;
缺點(diǎn):
1.不能隱藏明文的模式;
2.可能對(duì)明文進(jìn)行主動(dòng)攻擊;

3.2 CBC模式:

優(yōu)點(diǎn):
1.不容易主動(dòng)攻擊,安全性好于ECB,適合傳輸長(zhǎng)度長(zhǎng)的報(bào)文,是SSL、IPSec的標(biāo)準(zhǔn)。
缺點(diǎn):
1.不利于并行計(jì)算;
2.誤差傳遞;
3.需要初始化向量IV
3.3 CFB模式:

優(yōu)點(diǎn):
1.隱藏了明文模式;
2.分組密碼轉(zhuǎn)化為流模式;
3.可以及時(shí)加密傳送小于分組的數(shù)據(jù);
缺點(diǎn):
1.不利于并行計(jì)算;
2.誤差傳送:一個(gè)明文單元損壞影響多個(gè)單元;
3.唯一的IV;
3.4 OFB模式:

優(yōu)點(diǎn):
1.隱藏了明文模式;
2.分組密碼轉(zhuǎn)化為流模式;
3.可以及時(shí)加密傳送小于分組的數(shù)據(jù);
缺點(diǎn):
1.不利于并行計(jì)算;
2.對(duì)明文的主動(dòng)攻擊是可能的;
3.誤差傳送:一個(gè)明文單元損壞影響多個(gè)單元;
PKCS#5填充方式
參與運(yùn)算的兩個(gè)值,如果兩個(gè)相應(yīng)bit位相同,則結(jié)果為0,否則為1。
即:
0^0 = 0,
1^0 = 1,
0^1 = 1,
1^1 = 0
按位異或的3個(gè)特點(diǎn):
(1) 0^0=0,0^1=1 0異或任何數(shù)=任何數(shù)
(2) 1^0=1,1^1=0 1異或任何數(shù)-任何數(shù)取反
(3) 任何數(shù)異或自己=把自己置0
按位異或的幾個(gè)常見用途:
(1) 使某些特定的位翻轉(zhuǎn)
例如對(duì)數(shù)10100001的第2位和第3位翻轉(zhuǎn),則可以將該數(shù)與00000110進(jìn)行按位異或運(yùn)算。
10100001^00000110 = 10100111
(2) 實(shí)現(xiàn)兩個(gè)值的交換,而不必使用臨時(shí)變量。
例如交換兩個(gè)整數(shù)a=10100001,b=00000110的值,可通過下列語句實(shí)現(xiàn):
a = a^b; //a=10100111
b = b^a; //b=10100001
a = a^b; //a=00000110
(3) 在匯編語言中經(jīng)常用于將變量置零:
xor a,a
(4) 快速判斷兩個(gè)值是否相等
舉例1: 判斷兩個(gè)整數(shù)a,b是否相等,則可通過下列語句實(shí)現(xiàn):
return ((a ^ b) == 0)
舉例2: Linux中最初的ipv6_addr_equal()函數(shù)的實(shí)現(xiàn)如下:
static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
{
return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
a1->s6_addr32[1] == a2->s6_addr32[1] &&
a1->s6_addr32[2] == a2->s6_addr32[2] &&
a1->s6_addr32[3] == a2->s6_addr32[3]);
}
可以利用按位異或?qū)崿F(xiàn)快速比較, 最新的實(shí)現(xiàn)已經(jīng)修改為:
static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
{
return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
(a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
(a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
(a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
}
5 應(yīng)用通式:
對(duì)兩個(gè)表達(dá)式執(zhí)行按位異或。
result = expression1 ^ expression2
參數(shù)
result
任何變量。
expression1
任何表達(dá)式。
expression2
任何表達(dá)式。
說明
^ 運(yùn)算符查看兩個(gè)表達(dá)式的二進(jìn)制表示法的值,并執(zhí)行按位異或。該操作的結(jié)果如下所示:
0101 (expression1)1100 (expression2)----1001 (結(jié)果)當(dāng)且僅當(dāng)只有一個(gè)表達(dá)式的某位上為 1 時(shí),結(jié)果的該位才為 1。否則結(jié)果的該位為 0。
只能用于整數(shù)
下面這個(gè)程序用到了“按位異或”運(yùn)算符:
class E
{ public static void main(String args[ ])
{
char a1='十' , a2='點(diǎn)' , a3='進(jìn)' , a4='攻' ;
char secret='8' ;
a1=(char) (a1^secret);
a2=(char) (a2^secret);
a3=(char) (a3^secret);
a4=(char) (a4^secret);
System.out.println("密文:"+a1+a2+a3+a4);
a1=(char) (a1^secret);
a2=(char) (a2^secret);
a3=(char) (a3^secret);
a4=(char) (a4^secret);
System.out.println("原文:"+a1+a2+a3+a4);
}
}
就是加密啊解密啊
char類型,也就是字符類型實(shí)際上就是整形,就是數(shù)字.
計(jì)算機(jī)里面所有的信息都是整數(shù),所有的整數(shù)都可以表示成二進(jìn)制的,實(shí)際上計(jì)算機(jī)只認(rèn)識(shí)二進(jìn)制的.
位運(yùn)算就是二進(jìn)制整數(shù)運(yùn)算啦.
兩個(gè)數(shù)按位異或意思就是從個(gè)位開始,一位一位的比.
如果兩個(gè)數(shù)相應(yīng)的位上一樣,結(jié)果就是0,不一樣就是1
所以111^101=010
那加密的過程就是逐個(gè)字符跟那個(gè)secret字符異或運(yùn)算.
解密的過程就是密文再跟同一個(gè)字符異或運(yùn)算
010^101=111
至于為什么密文再次異或就變?cè)牧?這個(gè)稍微想下就知道了..