糊言亂語

          志未半斤, 才無八兩. 有苦有樂, 糊涂過活。
          posts - 25, comments - 7, trackbacks - 0, articles - 42
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2007年12月5日

          image

          posted @ 2008-07-11 11:25 Stanley Sun 閱讀(340) | 評論 (0)編輯 收藏

          眾所周知在計算機中所有的數(shù)據(jù)都是以二進制的方式存儲的。不管是int,String,float等等不同的數(shù)據(jù)類型,最終都會保存為01的形式。那么為什么要使用這種方式儲存數(shù)據(jù)呢?

          因為計算機是一種電子設(shè)備,由復(fù)雜的電子元器件組合而成,一個電子元器件有帶電和不帶電兩種狀態(tài),通常我們將帶電狀態(tài)表示為數(shù)值1,不帶電狀態(tài)表示為數(shù)值0,多個這樣的元器件的組合可以表示更多狀態(tài),也就是可以表示更多的數(shù)據(jù),如000表示0,001表示1,010表示2,011表示3,依此類推,111表示 7,一個元器件可表示一位(bit)數(shù)據(jù),這種表示數(shù)據(jù)的方式就叫二進制。
          在實際的電子設(shè)備中,我們將8個這樣的元器件形成一個單元,這樣的單元叫一個字節(jié)(byte),一個字節(jié)能表示多少個數(shù)呢?表示數(shù)值的范圍是0-255。
          一個字節(jié)由8個二進位組成,其中最右邊的一位稱為“最低有效位”或“最低位”,最左邊的一位稱為“最高有效位”或“最高位”。每一個二進位的值是0或1。

          二進制計數(shù)的缺點:書寫太長,容易出錯,一般計算機的數(shù)據(jù)位數(shù)都是4的整數(shù)倍,所以,在計算機里通常采用16進制計數(shù)法。用數(shù)字可以表示各種信息,計算機里只有數(shù)值,當(dāng)你在內(nèi)存中看到一個數(shù)值時,這個數(shù)值可能代表各種意義,生活中的數(shù)值也可以代表其他意義,如1234可以代表密碼,存款額,電報信息,根據(jù)上下線索,我們就能夠知道這數(shù)值代表的意義

           

          但是在Java中到底是如何去保存數(shù)據(jù)的呢?下面我就以int數(shù)據(jù)類型為例說明Java的方式。

          大家都知道在Java中規(guī)定1 int = 4 byte, 1 byte = 8 bit。以此推理那么1個int在計算機中就是以4 * 8 = 32位(bit)的方式存儲的。而又由于java中的int是屬于有符號類型(Java中不存在unsigned類型),所以32位的高一位是符號位,由此可以推理出int的儲存大小區(qū)間

          Integer.MAX_VALUE = 2147483647(十進制) = 1111111 11111111 11111111 11111111(二進制)
          Integer.MIN_VALUE = -2147483648(十進制) = 10000000 00000000 00000000 00000000(二進制)

          現(xiàn)在我們知道了二進制的概念了,但是其實二進制我想我們想象的那么單純的表示的,他們是不同的表現(xiàn)方式如:原碼,反碼,補碼

        1. 原碼
          將最高位作為符號位(以0代表正,1代表負),其余各位代表數(shù)值本身的絕對值(以二進制表示)。
                      為了簡單起見,我們用1個字節(jié)來表示一個整數(shù)。
                      +7的原碼為: 00000111
                       -7的原碼為: 10000111
        2. 反碼
                一個數(shù)如果為正,則它的反碼與原碼相同;一個數(shù)如果為負,則符號位為1,其余各位是對原碼取反。
                      為了簡單起見,我們用1個字節(jié)來表示一個整數(shù)。
                      +7的反碼為: 00000111
                       -7的反碼為: 11111000
        3. 補碼
              利用溢出,我們可以將減法變成加法。
              對于十進制數(shù),如果從9得到結(jié)果5,可以用減法:
                   9-4=5
                因為4+6=10,我們將6作為4的補數(shù),將上式的減法改寫為加法:
                   9+6=15
                去掉高位1(也就是減去10),得到結(jié)果5。
                對于16進制數(shù),如果從C得到結(jié)果5,可以用減法:
                   C-7=5
                因為7+9=16,我們將9作為7的補數(shù),將上式的減法改寫為加法:
                   C+9=15
                去掉高位1(也就是減去16),得到結(jié)果5。
                在計算機中,如果我們用1個字節(jié)表示一個數(shù),一個字節(jié)有8位,超過8位就進1,在內(nèi)存中情況為:
                     1 00000000
              進位1被丟棄。
              一個數(shù)如果為正,則它的原碼、反碼、補碼相同;一個數(shù)如果為負,則符號位為1,其余各位是對原碼取反,然后整個數(shù)加1。
                      為了簡單起見,我們用1個字節(jié)來表示一個整數(shù)。
                      +7的補碼為: 00000111
                      -7的補碼為:第一步:11111000 (符號位為,其余各位取反)
                                            第二步:11111001 (整個數(shù)加1)
                     +0的補碼:00000000;
                     -0的補碼:11111111;(第一步)
                                    100000000;(第二步)
          已知一個負數(shù)的補碼,將其轉(zhuǎn)換為十進制數(shù),步驟:
                1、先對各位取反;
                2、將其轉(zhuǎn)換為十進制數(shù);
                3、加上負號,再減去1。
                例如:
                11111010,最高位為1,是負數(shù),先對各位取反得00000101,轉(zhuǎn)換為十進制數(shù)得5,加上負號得-5,再減1得-6。
        4.  

          那么我們就知道了1與-1的二進制形式分別為0000000 00000000 00000000 00000001和11111111 11111111 11111111 11111111(Java中的數(shù)據(jù)是以補碼的形式儲存的)了。那么現(xiàn)在我們知道了數(shù)據(jù)是如何儲存的了。那么計算機是如何利用這些數(shù)據(jù)進行計算的呢?我們知道在計算機的CPU中只有一個加法器,所有的運算都是需要它進行的。所以在計算機里所有的加減乘除都是轉(zhuǎn)換成加法來進行運算的。那么它們是怎么轉(zhuǎn)換的呢?下面我們介紹一下二進制的運算操作

        5. 位運算符
          為了方便對二進制位進行操作,Java給我們提供了四個二進制位操作符:
          &          按位與
          |           按位或
          ^          按位異或
          ~          按位取反
        6. 按位
              一個房間里有兩個開關(guān)控制房間的燈的明暗。當(dāng)兩個開關(guān)同時處于打開狀態(tài)時,燈才能亮。
               開關(guān)1                   開關(guān)2                         燈的狀態(tài)
                 關(guān)                         關(guān)                              暗
                開                          關(guān)                              暗
                關(guān)                          開                              暗
                開                          開                              亮
          結(jié)論:按位與,只有壹(1)壹(1)為1。
        7. 按位
              一個房間里有兩個開關(guān)控制房間的燈的明暗。當(dāng)任何一個開關(guān)處于打開狀態(tài)時,燈就能亮。
              開關(guān)1                     開關(guān)2                     燈的狀態(tài)
                 關(guān)                         關(guān)                              暗
                開                          關(guān)                              亮
                關(guān)                          開                              亮
                開                          開                              亮
          結(jié)論:按位或,只有零(0)零(0)為0。
        8. 按位異或
              一個房間里有兩個開關(guān)控制房間的燈的明暗。當(dāng)兩個開關(guān)處于不同狀態(tài)時,燈就能亮。
             開關(guān)1                    開關(guān)2                       燈的狀態(tài)
                關(guān)                          關(guān)                              暗
                開                          關(guān)                              亮
                關(guān)                          開                              亮
                開                          開                              暗
          結(jié)論:按位異或,只有零(0)壹(1)或壹(1)零(0)為1。
        9. 按位取反
          結(jié)論:對二進制數(shù)按位取反,即0變成1,1變成0。
        10. Java中有三個移位運算符
          左移:<<              (相當(dāng)于 乘以2)
          帶符號右移:>>     (相當(dāng)于 除以2)
          無符號右移:>>>
            數(shù)            x                   x<<2                 x>>2              x>>>2
          17      00010001    00 01000100      00000100 01     00000100 01
          -17     11101111     11 10111100      11111011 11     00111011 11
        11. posted @ 2008-06-14 15:25 Stanley Sun 閱讀(1076) | 評論 (0)編輯 收藏

          概念:

          1.數(shù)字摘要:解決在安全的通信環(huán)境下,保證信息的唯一的一種方式。通常使用MD5/SHA-1等算法完成摘要。一般比如大家在網(wǎng)上下載軟件光盤時都會看到一個MD5值就是起到這個數(shù)字摘要的作用。在網(wǎng)絡(luò)的環(huán)境中發(fā)送者把消息和數(shù)字摘要一同發(fā)送給接收者,接收者使用發(fā)送者相同的算法對消息加密,看是否與發(fā)送者發(fā)送過來的數(shù)字摘要相同,如果相同就證明消息沒有給篡改過。下面是一個最為簡單的示例:

          import java.security.*;
          public class myDigest {
            public static void main(String[] args)  {
              myDigest my=new myDigest();
              my.testDigest();
            }
            public void testDigest()
            {
             try {
               String myinfo="我的測試信息";
              //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
                java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
                alga.update(myinfo.getBytes());
                byte[] digesta=alga.digest();
                System.out.println("本信息摘要是:"+byte2hex(digesta));
                //通過某中方式傳給其他人你的信息(myinfo)和摘要(digesta) 對方可以判斷是否更改或傳輸正常
                java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");
                algb.update(myinfo.getBytes());
                if (algb.isEqual(digesta,algb.digest())) {
                   System.out.println("信息檢查正常");
                 }
                 else
                  {
                    System.out.println("摘要不相同");
                   }
             }
             catch (java.security.NoSuchAlgorithmException ex) {
               System.out.println("非法摘要算法");
             }
            }
            public String byte2hex(byte[] b) //二行制轉(zhuǎn)字符串
              {
               String hs="";
               String stmp="";
               for (int n=0;n<b.length;n++)
                {
                 stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
                 if (stmp.length()==1) hs=hs+"0"+stmp;
                 else hs=hs+stmp;
                 if (n<b.length-1)  hs=hs+":";
                }
               return hs.toUpperCase();
              }
          }
          

          2.電子簽名:對數(shù)據(jù)信息的發(fā)生者身份的認定,它是一種抽象的概念而不是一種具體技術(shù)。實現(xiàn)電子簽名的技術(shù)手段目前有多種,比如基于公鑰密碼技術(shù)的數(shù)字簽名;或用一個獨一無二的以生物特征統(tǒng)計學(xué)為基礎(chǔ)的識別標(biāo)識,例如手印、聲音印記或視網(wǎng)膜掃描的識別;手書簽名和圖章的電子圖象的模式識別;表明身份的密碼代號(對稱算法);基于量子力學(xué)的計算機等等。


          3.數(shù)字簽名:所謂數(shù)字簽名就是利用通過某種密碼運算生成的一系列符號及代碼組成電子密碼進行"簽名",來代替書寫簽名或印章,對于這種電子式的簽名在技術(shù)上還可進行算法驗證,其驗證的準(zhǔn)確度是在物理世界中與手工簽名和圖章的驗證是無法相比的。一般實現(xiàn)數(shù)字簽名的方法是通過生成的密鑰對的私鑰對用戶生成的數(shù)字消息進行DSA(Digital Signature Algorithm (DSA)是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSS(DigitalSignature Standard))加密實現(xiàn)的。實現(xiàn)代碼如下:

             */
           import java.security.*;
           import java.security.spec.*;
          public class testdsa {
            public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
                  testdsa my=new testdsa();
                  my.run();
            }
            public void run()
            {
            //數(shù)字簽名生成密鑰
            //第一步生成密鑰對,如果已經(jīng)生成過,本過程就可以跳過,對用戶來講myprikey.dat要保存在本地
            //而mypubkey.dat給發(fā)布給其它用戶
             if ((new java.io.File("myprikey.dat")).exists()==false) {
                 if (generatekey()==false) {
                     System.out.println("生成密鑰對敗");
                     return;
                    };
                  }
          //第二步,此用戶
          //從文件中讀入私鑰,對一個字符串進行簽名后保存在一個文件(myinfo.dat)中
          //并且再把myinfo.dat發(fā)送出去
          //為了方便數(shù)字簽名也放進了myifno.dat文件中,當(dāng)然也可分別發(fā)送
            try {
            java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
            PrivateKey myprikey=(PrivateKey)in.readObject();
            in.close();
           // java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
           //java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
            String myinfo="這是我的信息";    //要簽名的信息
            //用私鑰對信息生成數(shù)字簽名
            java.security.Signature signet=java.security.Signature.getInstance("DSA");
            signet.initSign(myprikey);
            signet.update(myinfo.getBytes());
            byte[] signed=signet.sign();  //對信息的數(shù)字簽名
            System.out.println("signed(簽名內(nèi)容)="+byte2hex(signed));
           //把信息和數(shù)字簽名保存在一個文件中
            java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
            out.writeObject(myinfo);
            out.writeObject(signed);
            out.close();
            System.out.println("簽名并生成文件成功");
            }
            catch (java.lang.Exception e) {
              e.printStackTrace();
              System.out.println("簽名并生成文件失敗");
            };
            //第三步
            //其他人通過公共方式得到此戶的公鑰和文件
            //其他人用此戶的公鑰,對文件進行檢查,如果成功說明是此用戶發(fā)布的信息.
            //
            try {
             java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
             PublicKey pubkey=(PublicKey)in.readObject();
             in.close();
             System.out.println(pubkey.getFormat());
             in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
             String info=(String)in.readObject();
             byte[] signed=(byte[])in.readObject();
             in.close();
            java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
            signetcheck.initVerify(pubkey);
            signetcheck.update(info.getBytes());
            if (signetcheck.verify(signed)) {
            System.out.println("info="+info);
             System.out.println("簽名正常");
            }
            else  System.out.println("非簽名正常");
            }
            catch (java.lang.Exception e) {e.printStackTrace();};
            }
            //生成一對文件myprikey.dat和mypubkey.dat---私鑰和公鑰,
            //公鑰要用戶發(fā)送(文件,網(wǎng)絡(luò)等方法)給其它用戶,私鑰保存在本地
            public boolean generatekey()
            {
              try {
            java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA");
           // SecureRandom secrand=new SecureRandom();
           // secrand.setSeed("tttt".getBytes()); //初始化隨機產(chǎn)生器
           // keygen.initialize(576,secrand);     //初始化密鑰生成器
            keygen.initialize(512);
            KeyPair keys=keygen.genKeyPair();
          //  KeyPair keys=keygen.generateKeyPair(); //生成密鑰組
            PublicKey pubkey=keys.getPublic();
            PrivateKey prikey=keys.getPrivate();
            java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
            out.writeObject(prikey);
            out.close();
            System.out.println("寫入對象 prikeys ok");
            out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
             out.writeObject(pubkey);
             out.close();
             System.out.println("寫入對象 pubkeys ok");
             System.out.println("生成密鑰對成功");
             return true;
            }
            catch (java.lang.Exception e) {
             e.printStackTrace();
             System.out.println("生成密鑰對失敗");
             return false;
             };
            }
            public String byte2hex(byte[] b)
              {
               String hs="";
               String stmp="";
               for (int n=0;n<b.length;n++)
                {
                 stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
                 if (stmp.length()==1) hs=hs+"0"+stmp;
                 else hs=hs+stmp;
                 if (n<b.length-1)  hs=hs+":";
                }
               return hs.toUpperCase();
              }
          }    把他的公鑰的信息及簽名發(fā)給其它用戶
          


          4.PKI(公鑰基礎(chǔ)設(shè)施):

          posted @ 2007-12-05 22:09 Stanley Sun 閱讀(543) | 評論 (1)編輯 收藏

          主站蜘蛛池模板: 东乡县| 沁水县| 峨边| 九龙坡区| 高唐县| 丰城市| 五指山市| 凉山| 确山县| 莱芜市| 昌乐县| 灵山县| 合作市| 阿勒泰市| 张掖市| 石渠县| 安阳县| 金溪县| 洛浦县| 浠水县| 沭阳县| 志丹县| 双峰县| 新沂市| 揭东县| 襄汾县| 盐亭县| 乌海市| 广宁县| 特克斯县| 宣汉县| 建平县| 荥经县| 长武县| 阳朔县| 县级市| 彝良县| 同德县| 区。| 遵化市| 元氏县|