多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 深入理解Android之Java Security第一部分

深入理解Android之Java Security第一部分

來源:程序員人生   發布時間:2015-04-11 09:10:51 閱讀次數:11569次

深入理解Android之Java Security(第1部份)

從事Android工作4年以來,只有前1年不到的時間是用C++在開發東西(主要是開發DLNA組件,目前我已將它們全部開源,參考http://blog.csdn.net/innost/article/details/40216763),后面的工作幾近都在用Java。自以為Java相干的東西都見過了,可前段時間有個朋友給我花了1個多小時講授他們某套系統的安全部系結構,其中觸及到很多專業術語,比如Message Digest(消息摘要)、Digital Signature(數字簽名)、KeyStore(恕我不知道翻譯成甚么好,還是用英文原稱吧)、CA(Certificate Authority)等。我當時腦袋就大了,尼瑪弄Java這么久,歷來沒接觸過啊。為此,我特地到AndroidFramework代碼中查詢了下,Android平臺里與之相干的東西還有1個KeyChain。

原來,上述內容都屬于Java世界中1個早已存在的知識模塊,那就是JavaSecurity。Java Security包括很多知識點,常見的有MD5,DigitalSignature等,而Android在Java Seurity以外,拓展了1個android.security包,此包中就提供了KeyChain。

本文將介紹Java Security相干的基礎知識,然后介紹下Android平臺上與之相干的使用處景。

實際上,在1些金融,銀行,電子支付方面的利用程序中,JavaSecurity使用的地方非常多。

代碼路徑:

  • Security.java:libcore/lunl/src/main/java/java/security/
  • TrustedCertificateStore.java:libcore /crypto/src/main/java/org/conscrypt/

本文例子:

https://code.csdn.net/Innost/androidsecuritydemo  目前已公然。

1  Java Security背景知識

Java Security實際上是Java平臺中1個比較獨立的模塊。除軟件實現上內容外,它實際上對應了1系列的規范。從Java2開始,Java Security包括主要3個重要的規范:

  • JavaCryptography Extension(簡寫為JCE),JCE所包括的內容有加解密,密鑰交換,消息摘要(Message Digest,比如MD5等),密鑰管理等。本文所觸及的大部份內容都屬于JCE的范疇。
  • JavaSecure Socket Extension(簡寫為JSSE),JSSE所包括的內容就是Java層的SSL/TLS。簡單點說,使用JSSE就能夠創建SSL/TLS socket了。
  • JavaAuthentication and Authorization Service(簡寫為JAAS),JSSA和認證/授權有關。這部份內容在客戶端接觸得會比較少1點,所以本文不擬討論它。

在上述3個子模塊或規范中,JCE是JavaSecurity的大頭,其他兩個子模塊JSSE和JAAS都依賴于它,比如SSL/TLS在工作進程中需要使用密鑰對數據進行加解密,那末密鑰的創建和使用就依托JCE子模塊了。

另外,既然和安全相干,那末對安全敏感的相干部門或政府肯定會有所干涉。Java是在美國被發明的,所以美國政府對Java Security方面的出口(比如哪些模塊,哪些功能能給其他國家使用)有相干的限制。例如,不允許出口的JCE(從軟件實現上看,可能就是從Java官網上下載到的幾個Jar包文件)支持1些高級的加解密功能(比如在密鑰長度等方面有所限制)。

注意,Java Security包括的內容非常多,而本文將重點關注Java SecurityAPI與其使用方法方面的知識。對Java Security其他細節感興趣的同學可在瀏覽完本文后,再瀏覽參考文獻[1]。

 

1.1  JCE介紹

1.1.1  JCE設計架構介紹

介紹JCE之前,先來說解下JCE的設計架構。JCE在設計時重點關注兩個問題:

  • 其功能具體實現的獨立性和可互操作性。
  • 使用算法的獨立性和可擴大性。

對獨立性而言,1個最通用的做法就是把定義和實現通過抽象類或基類的方式進行解耦合。在JCE中:

  • 它首先把功能組合成1個1個的Service(也稱作Engine)。比如,對應“加解密”的API組合成CipherService,對應“消息摘要”的API組合成MessageDigest Service,對應“簽名”的API組合成SignatureService。JCE為這些Service都定義了1個諸如XXXSpi的抽象類。其中,SPI是Service Provider Interface的縮寫。
  • 上述SPI的具體實現則由不同的Provider來提供。比如JDK會提供1組默許的實現(固然,這些實現之前是由Sun公司,現在由Oracle提供。在這個時候,前面提到的政府管制就可以插1腳了)。注意,Provider可以提供1組Service的實現,也能夠提供單個Service的實現。

注意,可互操作性是指Provider A實現的MD5值,能被Provider B辨認。明顯,這個要求是公道的。

圖1所示為JCE中1些類的定義:


圖1  JCE中1些類的定義

圖1展現了JCE中的1些類定義。大家先關注左下角的Provider和Security類:

  • Security是java.security包的主要管理類。通過它可向JCE框架注冊不同的Provider。
  • Android平臺上,每個利用程序在啟動的時候都會默許注冊1個類型為AndroidKeyStoreProvider的對象。

注意,由于歷史緣由,JCE的Service分散定義在好些個Package中:

  • java.security:此Package包括最多的Service定義。
  • javax.crypto:此package包括加解密相干的Service定義。

上述這兩個package都屬于JCE的內容。從使用者的角度來看,其實不太需要關注它們到底定義在哪一個Package中(代碼中通過1句import xxx就能夠把對應的包引入,后續編寫代碼時候,直接使用相干類就行了)。

BTW,個人感覺Java類定義非常多,而且有些類和它們所在包的關系仿佛有些混亂。

 

(1)  Android平臺中Provider的注冊

前面已說過,JCE框架對使用者提供的是基礎類(抽象類或接口類),而具體實現需要有地方注冊到JCE框架中。所以,我們來看看Android平臺中,JCE框架都注冊了哪些Provider:

[-->Security.java]

static {

   boolean loaded = false;

   try {

       //從資源文件里搜索是不是有security.properties定義,Android平臺是沒有這個文件的

      InputStreamconfigStream =

         Security.class.getResourceAsStream("security.properties");

       InputStream input = newBufferedInputStream(configStream);

       secprops.load(input);

       loaded = true;

       configStream.close();

        }......

     if (!loaded) {//注冊默許的Provider

        registerDefaultProviders();

     }

      ......

    }

 

   private static void registerDefaultProviders() {

     /*

    JCE對Provider的管理非常簡單,就是將Provider類名和對應的優先級存在屬性列表里

    比以下面的:OpenSSLProvider,它對應的優先級是1.

     優先級是甚么意思呢?前面說過,不同的Provider可以實現同1個功能集合,比如都實現

     MessageDigestSpi。那末用戶在創建MessageDigest的實例時,如果沒有指明Provider名,

     JCE默許從第1個(依照優先級,由1到n)Provider開始搜索,直到找到第1個實現了

     MessageDigestSpi的Provider(比如Provider X)為止。然后,MessageDigest的實例

      就會由Provider X創建。圖2展現了1個例子

    */

     secprops.put("security.provider.1",

           "com.android.org.conscrypt.OpenSSLProvider");

     secprops.put("security.provider.2",

            "org.apache.harmony.security.provider.cert.DRLCertFactory");

    secprops.put("security.provider.3",

       "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");

    secprops.put("security.provider.4",

        "org.apache.harmony.security.provider.crypto.CryptoProvider");

      //JSSE有關

      secprops.put("security.provider.5",

        "com.android.org.conscrypt.JSSEProvider");

 }

圖2展現了Provider優先級使用的例子:


圖2  Provider優先級示例

圖2中:

  • 左側的Application要使用MD5算法來創建1個MessageDigest實例。而左下角有3個Provider(A、B、C)。其中B和C支持MD5算法。所以JCE會使用第1個實現MD5算法的Provider(即Provider B)來創建MessageDigest實例。
  • 右側的Application也要使用MD5算法來創建MD實例。但是它在參數中指明了Provider的名字(“ProviderC”),所以JCE就會直接使用ProviderC來創建這個MD實例。

注意,圖2中的SHA⑴/256和MD5都是MessageDigest的1種算法,本文后面會介紹它們。

(2) AndroidKeyStoreProvider

Android平臺中,每一個利用程序啟動時都會注冊1個類型為“AndroidKeyStoreProvider”的對象。這是在ActivityThread中完成的,代碼以下所示:

[-->ActivityThread.java::main]

public static void main(String[] args) {

   ......

  Security.addProvider(new AndroidKeyStoreProvider());

  ......

}

來看看AndroidKeyStoreProvider是甚么,代碼以下所示:

[-->AndroidKeyStoreProvider::AndroidKeyStoreProvider]

public class AndroidKeyStoreProvider extends Provider {

  public static final StringPROVIDER_NAME = "AndroidKeyStore";

  publicAndroidKeyStoreProvider() {

    super(PROVIDER_NAME, 1.0,"Android KeyStore security provider");

    put("KeyStore." + AndroidKeyStore.NAME,

          AndroidKeyStore.class.getName());

    put("KeyPairGenerator.RSA",AndroidKeyPairGenerator.class.getName());

  }

}

AndroidKeyStoreProvider很簡單,但是看上去還是不明白它是干甚么的?其實,這個問題的更深層次的問題是:Provider是干甚么的?

  • Provider從Properties類派生。Properties本質上是1個屬性列表,也就是它保存了1串的屬性名和對應的屬性值。
  • 從圖2的例子可知,利用程序只說要創建MD5的MessageDigest實例。在代碼中,“MD5”是1個字符串,而MessageDigest實例肯定是由某個類創建的(假定這個類名叫com.md5.test)。那末,這個“MD5”字符串就是1個Key,對應的屬性值就是這個類的類名(“com.md5.test”)。JCE根據屬性key,找到屬性value,然后創建這個類的實例就完成了工作!

固然,Provider的內容和功能比這要復雜,不過我們對Provider的實現沒甚么興趣,大家只要知道它存儲了1系列的屬性key和value就能夠了。JCE會根據情況去查詢這些key和對應的value。

(3)  實例介紹

來個例子,看看Android系統上都有哪些Provider:

[-->DemoActivity.java::testProvider]

void testProvider(){

   e(TAG, "***Begin TestProviders***");

   //獲得系統所有注冊的Provider

   Provider[] providers = Security.getProviders();

   for(Providerprovider:providers){

      //輸出Provider名

      e(TAG,"Provider:" + provider+" info:");

      //前面說了,provider其實就是包括了1組key/value值。下面將打印每一個Provider的

      //這些信息

      Set<Entry<Object,Object>>allKeyAndValues = provider.entrySet();

     Iterator<Entry<Object, Object>> iterator =allKeyAndValues.iterator();

      while(iterator.hasNext()){

        Entry<Object,Object> oneKeyAndValue =iterator.next();

        Object key = oneKeyAndValue.getKey();

        Object value =oneKeyAndValue.getValue();

        //打印Key的類型和值

       e(TAG,"===>" + "Keytype="+key.getClass().getSimpleName()+"

                           Key="+key.toString());

        //打印Value的類型和值

      e(TAG,"===>" + "Valuetype="+value.getClass().getSimpleName()+"

                           Value="+value.toString());

        }

     }

     e(TAG, "***End TestProviders*** ");

 }

在控制臺中,通過adb logcat | grep ASDemo就能夠顯示testProvider的輸出信息了,如圖3所示:


圖3  testProvider輸出示例

圖3打出了AndroidOpenSSLprovider的信息:

  • 其中Key和Value的類型都是String。
  • Key的值其實都是JCE中1些Service或算法的名稱或別名。此處先不討論這些細節,以后碰到再說。

了解完JCE框架后,我們分別來介紹JCE中的1些重要Service。

1.1.2  Key知識介紹

談到安全,大家第1想到的就是密鑰,即Key。那末大家再仔細想一想下面這兩個問題:

  • Key從何而來?即代碼中怎樣創建Key。
  • Key怎樣傳遞給外部使用者?外部使用者多是1個開發者,這時候候就不能把代碼中的1個對象通過email發給他了,而是要把Key的書面表達情勢(參考資料[1]把它叫做externalrepresentations,即外部表達情勢。我為了強調這類表達情勢,把它稱為書面表達情勢。便可有把Key寫到文檔里,發給其他人)發給人家。

圖4解釋了上述問題:


圖4  Key示意

圖4中:

  • Key怎樣創建?在JCE中是通過Generator類創建的,這時候候在代碼中得到的是1個Key實例對象。
  • Key怎樣傳遞?這就觸及到如何書面表達Key了,最最經常使用的方式就是把它表示成16進制(比如圖4中下部Encoded Key Data“0AF34C4E56...”)。或,由于Key產生是基于算法的,這時候候就能夠把參與計算的關鍵變量的值弄出來。比如圖4右上角的“Param P=3,ParamQ=4”。所以,Key的書面表達情勢有兩種,1種是16進制密鑰數據,1種是基于算法的關鍵變量(這類方式叫KeySpecification)。
  • 爾后,我們可以把16進制或關鍵變量發給對方。對方拿到Key的書面表達式后,下1步要做的就是還原出代碼中的key對象。這時候候要用到的就是KeyFactory了。所以,KeyFactory的輸入是Key的2進制數據或KeySpecification,輸出就是Key對象。

在安全領域中,Key分為兩種:

  • 對稱Key:即加密和解密用得是同1個Key。JCE中,對稱key的創建由KeyGenerator類來完成。
  • 非對稱Key:即加密和解密用得是兩個Key。這兩個Key構成1個Key對(KeyPair)。其中1個Key叫公鑰(PublicKey),另外1個Key叫私鑰(PrivateKey)。公鑰加密的數據只能用私鑰解密,而私鑰加密的數據只能用公鑰解密。私鑰1般自己保存,而公鑰是需要發給合作方的。(此處我們還不討論公鑰和私鑰的使用處景,僅限介紹公鑰和私鑰的概念)。JCE中,非對稱Key的創建由KeyPairGenerator類來完成。

圖5所示為JCE中Key相干的類和繼承關系。


圖5  JCE Key相干類

圖5中:

  • PublicKey,PrivateKey和SecretKey都派生自Key接口。所以,這3個類也是接口類,而且沒有定義新的接口。
  • DSAPublicKey和RSAPublicKey也派生自PublicKey接口。DSA和RSA是兩種不同的算法。

(1)  Key實例介紹

先來看對稱key的創建和導入(也就是把Key的書面表達導入到程序中并生成Key對象)

[-->DemoActivity.java::testKey]

{//對稱key即SecretKey創建和導入

     //假定雙方約定使用DES算法來生成對稱密鑰

     e(TAG,"==>secret key: generated it using DES");

     KeyGeneratorkeyGenerator = KeyGenerator.getInstance("DES");

     //設置密鑰長度。注意,每種算法所支持的密鑰長度都是不1樣的。DES只支持64位長度密鑰

     //(或許是算法本身的限制,或是不同Provider的限制,或是政府管制的限制

     keyGenerator.init(64);

     //生成SecretKey對象,即創建1個對稱密鑰

     SecretKey secretKey = keyGenerator.generateKey();

     //獲得2進制的書面表達

     byte[] keyData =secretKey.getEncoded();

     //平常使用時,1般會把上面的2進制數組通過Base64編碼轉換成字符串,然后發給使用者

     String keyInBase64 =Base64.encodeToString(keyData,Base64.DEFAULT);

     e(TAG,"==>secret key: encrpted data ="+ bytesToHexString(keyData));

     e(TAG,"==>secrety key:base64code=" + keyInBase64);

     e(TAG,"==>secrety key:alg=" + secretKey.getAlgorithm());

    

    //假定對方收到了base64編碼后的密鑰,首先要得到其2進制表達式

   byte[] receivedKeyData =Base64.decode(keyInBase64,Base64.DEFAULT);

   //用2進制數組構造KeySpec對象。對稱key使用SecretKeySpec類

   SecretKeySpec keySpec =new SecretKeySpec(receivedKeyData,”DES”);

   //創建對稱Key導入用的SecretKeyFactory

   SecretKeyFactorysecretKeyFactory = SecretKeyFactory.getInstance(”DES”);

   //根據KeySpec還原Key對象,即把key的書面表達式轉換成了Key對象

   SecretKey receivedKeyObject = secretKeyFactory.generateSecret(keySpec);

   byte[]encodedReceivedKeyData = receivedKeyObject.getEncoded();

   e(TAG,"==>secret key: received key encoded data ="

                                +bytesToHexString(encodedReceivedKeyData));

如果1切正常的話,紅色代碼和綠色代碼打印出的2進制表示應當完全1樣。此測試的結果如圖6所示:


圖6  SecretKey測試結果

此處有幾點說明:

  • 對稱key的創建有不同的算法支持,根據參考資料[1],1般有Blowfish, DES, DESede,HmacMD5,HmacSHA1,PBEWithMD5AndDES, and PBEWithMD5AndTripleDES這些算法。但是Android平臺,乃至不同手機是不是都支持這些算法,則需要在testProvider那個例子去查詢。
  • 另外,KeyGenerator如果支持上面的算法,但是SecretKeyFactory則不1定支持。比如ScreteKeyFactory則不支持HmacSHA1。

注意,本文會討論太多算法相干的內容。

再來看KeyPair的用例:

[-->DemoActivity.java::KeyPair測試]

{//public/private key test

  e(TAG, "==>keypair: generated it using RSA");

  //使用RSA算法創建KeyPair

  KeyPairGeneratorkeyPairGenerator = KeyPairGenerator.getInstance("RSA");

  //設置密鑰長度

  keyPairGenerator.initialize(1024);

  //創建非對稱密鑰對,即KeyPair對象

  KeyPair keyPair =keyPairGenerator.generateKeyPair();

  //獲得密鑰對中的公鑰和私鑰對象

  PublicKey publicKey =keyPair.getPublic();

  PrivateKey privateKey =keyPair.getPrivate();

  //打印base64編碼后的公鑰和私鑰值

  e(TAG,"==>publickey:"+bytesToHexString(publicKey.getEncoded()));

  e(TAG, "==>privatekey:"+bytesToHexString(privateKey.getEncoded()));

 

  /*

   現在要斟酌如何把公鑰傳遞給使用者。雖然可以和對稱密鑰1樣,把2進制數組取出來,但是

   對非對稱密鑰來講,JCE不支持直接通過2進制數組來還原KeySpec(多是算法不支持)。

   那該怎樣辦呢?前面曾說了,除直接還原2進制數組外,還可以通過具體算法的參數來還原

   RSA非對稱密鑰就得使用這類方法:

   1 首先我們要獲得RSA公鑰的KeySpec。

  */

  //獲得RSAPublicKeySpec的class對象

  Class spec = Class.forName("java.security.spec.RSAPublicKeySpec");

   //創建KeyFactory,并獲得RSAPublicKeySpec

  KeyFactory keyFactory = KeyFactory.getInstance("RSA");

  RSAPublicKeySpecrsaPublicKeySpec =

            (RSAPublicKeySpec)keyFactory.getKeySpec(publicKey, spec);

  //對RSA算法來講,只要獲得modulusexponent這兩個RSA算法特定的參數就能夠了

  BigInteger modulus =rsaPublicKeySpec.getModulus();

  BigInteger exponent =rsaPublicKeySpec.getPublicExponent();

  //把這兩個參數轉換成Base64編碼,然后發送給對方

  e(TAG,"==>rsa pubkey spec:modulus="+

             bytesToHexString(modulus.toByteArray()));

  e(TAG,"==>rsa pubkey spec:exponent="+

             bytesToHexString(exponent.toByteArray()));

 

  //假定接收方收到了代表modulus和exponent的base64字符串并得到了它們的2進制表達式

  byte[] modulusByteArry =modulus.toByteArray();

  byte[] exponentByteArry =exponent.toByteArray();

  //由接收到的參數構造RSAPublicKeySpec對象

  RSAPublicKeySpecreceivedKeySpec = new RSAPublicKeySpec(

                    newBigInteger(modulusByteArry),

                    new BigInteger(exponentByteArry));

  //根據RSAPublicKeySpec對象獲得公鑰對象

  KeyFactoryreceivedKeyFactory = keyFactory.getInstance("RSA");

  PublicKey receivedPublicKey =

                 receivedKeyFactory.generatePublic(receivedKeySpec);

  e(TAG, "==>received pubkey:"+

                   bytesToHexString(receivedPublicKey.getEncoded()));

}

如果1切正常的話,上述代碼中紅色和黑色代碼段將輸出完全1樣的公鑰2進制數據。如圖7所示:


圖7  KeyPair測試示意圖

在Android平臺的JCE中,非對稱Key的經常使用算法有“RSA”、“DSA”、“Diffie?Hellman”、“Elliptic Curve (EC)”等。

(2)  Key知識小結

我自己在學習Key的時候,最迷惑的就是前面提到的兩個問題:

Key是甚么?雖然“密鑰”這個詞常常讓我聯想到實際生活中的鑰匙,但是在學習JavaSecurity之前,我1直不知道在代碼中(或編程時),它究竟是個甚么玩意。并且,它到底怎樣創建。

創建Key以后,我怎樣把它傳遞給其他人。就好比鑰匙1樣,你總得給個實物給人家吧?

現在來看這兩個問題的總結性回答:):

  • JCE中,Key根據加密方法的不同,分為對稱Key和非對稱Key兩大類。其中對稱Key由類SecretKey表達,而非對稱Key常常是公鑰和私鑰構成1個密鑰對。在程序里,他們的類型分別是PublicKey、PrivateKey和KeyPair。
  • SecretKey和KeyPair都有對應的Generator類來創建。其中,創建對稱Key的是KeyGenerator,創建KeyPair的是KeyPairGenerator。1方創建Key后,怎樣把密鑰信息傳遞給其他人呢?這時候就需要用到Key的外部表現情勢了(我把它叫做書面表達情勢)。
  • Key的書面表達式有兩種,1種是直接把它的2進制數組弄出來,然后編碼成base64發給對方。對方從這個base64編碼字符串中得到2進制數組。這個2進制數組叫KeyEncoded Data。怎樣把它轉換成代碼中的Key實例呢?對對稱Key來講,先用這個2進制數組構造1個SecretKeySpec,然后再用SecretKeyFactory構造出終究的SecretKey對象。
  • Key的另外1種表示式就是利用創建Key的算法。這個主要針對非對稱Key。Key創建時,總是需要依賴1些特定的算法,而這些算法也會有1些參數。類似于學數學時,算法對應于1個公式,我們只要把參數值帶入進去就可以得到結果1樣。所以,在這類情況下,我們只要把參數保存起來,然后傳遞給對方可以了。對方拿到這些個參數,再構造出對應算法所需要的KeySpec對象,最后由KeyPairFactory創建終究的Key對象。

不理解上述內容的同學,請把實例代碼再仔細看看!

 

1.1.3  Certificates知識介紹

JCE中,Certificates(是復數喔!)是證書之意。“證書”也是1個平常生活中經常使用的詞,但是在JCE中,或說在Java Security中,它有甚么用呢?

這個問題的答案還是和Key的傳遞有關系。前面例子中我們說,創建密鑰的人1般會把Key的書面表達情勢轉換成Base64編碼后的字符串發給使用者。使用者再解碼,然后還原Key就能夠用了。

上面這個流程本身沒有甚么隱患,但是,是否是隨便1個人(1個組織,1個機構等等等等)給你發1個key,你就敢用呢?簡單點說,你怎樣判斷是不是該信任給你發Key的某個人或某個機構呢?

好吧,這就好比現實生活中有個人說自己是警察,那你肯定得要他取出警官證或甚么別的東西來證明他是警察。這個警官證的作用就是證書的作用。

1般而言,我們會把Key的2進制表達式放到證書里,證書本身再填上其他信息(比如此證書是誰簽發的,甚么時候簽發的,有效期多久,證書的數字簽名等等)。

初看起來,好像證書比直接發base64字符串要正規點,1方面它包括了證書簽發者的信息,而且還有數字簽名以避免內容被篡改。

但是,證書解決了信任的問題嗎?很明顯是沒有的。由于證書是誰都可以制作的。既然不是人人都可以相信,那末,也不是隨意甚么證書都可以被信任。

怎樣辦?先來看現實生活中是怎樣解決信任問題的。

現實生活中也有很多證書,大到房產證、身份證,小到離職證明、介紹信。對方怎樣判斷你拿的這些證是真實有效的呢?

對頭,看證書是誰/或哪一個機構的“手墨”!比如,結婚證首先要看是否是民政局的章。那....民政局是不是應當被信任呢???

好吧。關于民政局是不是應當被信任的這個問題在技術上基本無解,它是1個死循環。由于,即便能找到另外1個機構證明民政局合法有效,但這個問題仍然會順流而上,說民政局該被信任的那個機構其本身是不是能被信任呢?....此問題終究會沒完沒了的問下去。

那怎樣辦?沒甚么好辦法。只要大家公認民政局能被信任,就能夠了。

同理,對證書的是不是可信任問題而言:

  • 首先,在全球范圍內(或是1個國家,1個地區)設置1些頂級證書簽發機構,凡是由這些證書簽發機構(CertificateAuthorities)簽發的證書,我們要無條件的信任(不斟酌其他捏造等因素,證書是不是被篡改可通過數字簽名來判斷)。就和民政局似的,不信民政局還信誰?:)。
  • 這么多證書要發,頂級CA肯定忙不過來,所以還可以設立各種級別的CA,比如北京市的民政局弄1個CA,湖南省的公安廳弄1個CA。這類級別的CA是不是該無條件信任呢?不1定。看你對它的了解。anyway,這個級別的CA可以把自己拿到頂級CA那去認個證。比方說,湖南省公安廳發了1個證書,它可以到頂級CA那去蓋個章。由于頂級CA是無條件信任的,所以湖南省公安廳這個證書可以被信任。
  • 公司A要發證書給客戶使用,最好是先拿到上1級或相干領域的CA(不1定是頂級CA)那去蓋個章。最后,公司A把蓋了章的證書a發給客戶使用就能夠了。

客戶拿到證書a后,首先要檢查下:

  • 客戶拿到證書a后,發現是某個CA簽發的。如果是頂級CA簽發的,那好辦,直接信任。如果不是頂級CA簽發的。客戶再去查看這個發證的CA能不能被信任,溯流而上,直到跟蹤到頂級CA為止。所以,證書,常常不是1個證書的事情,而是1個證書鏈的事情!
  • 另外,如果客戶本身就信任公司A,那其實公司A也不需要去找CA認證,直接把證書a給客戶就能夠了。固然,這個時候的證書a就不需要CA的章了。

......唧唧歪歪半天,其實關于證書的核心問題就1個:

證書背后常常是1個證書鏈。

  • 大家不要小視這個問題。證書鏈常常會把問題弄復雜。比如甲方有CA A簽發的證書,而乙方有CA B簽發的證書。那末甲乙雙方要相互信任的話,得把甲乙雙方證書鏈上的證書都弄過來校驗1遍,直到頂級CA為止。固然,甲乙證書鏈的頂級CA可能還不是同1個。

.......

為了方便,系統(PC,Android,乃至閱讀器)等都會把1些頂級CA(也叫Root CA,即根CA)的證書默許集成到系統里。這些RootCA用作自己身份證明的證書(包括該CA的公鑰等信息)叫根證書。根證書理論上是需要被信任的。以Android為例,它在libcore/luni/src/main/files/cacerts下放了150多個根證書(以Android 4.4為例),如圖8所示:


圖8  Android自帶的根證書文件

我們隨意打開1個根證書文件看看,以下所示:

[某證書文件的內容,用記事本打開便可]

-----BEGIN CERTIFICATE-----

MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC

VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD

ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v

dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0

MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww

KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G

A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi

MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13

5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE

SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O

JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu

ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE

AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB

AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB

CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw

b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo

7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/

0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7

nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx

x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ

33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=

-----END CERTIFICATE-----

Certificate:  #下面是證書的明文內容

    Data:

        Version: 3 (0x2)

        Serial Number:971282334 (0x39e4979e)

    Signature Algorithm: sha1WithRSAEncryption

        Issuer: C=US, O=Wells Fargo, OU=Wells Fargo CertificationAuthority, CN=Wells Fargo Root Certificate Authority

        Validity

            Not Before: Oct11 16:41:28 2000 GMT

            Not After : Jan14 16:41:28 2021 GMT

        Subject: C=US, O=Wells Fargo, OU=Wells Fargo CertificationAuthority, CN=Wells Fargo Root Certificate Authority

        Subject Public Key Info:#Public KeyKeySpec表達式

            Public Key Algorithm: rsaEncryption  #PublicKey的算法

                Public-Key: (2048 bit)

                Modulus:

                   00:d5:a8:33:3b:26:f9:34:ff:cd:9b:7e:e5:04:47:

                   ce:00:e2:7d:77:e7:31:c2:2e:27:a5:4d:68:b9:31:

                   ba:8d:43:59:97:c7:73:aa:7f:3d:5c:40:9e:05:e5:

                    a1:e2:89:d9:4c:b8:3f:9b:f9:0c:b4:c8:62:19:2c:

                   45:ae:91:1e:73:71:41:c4:4b:13:fd:70:c2:25:ac:

                   22:f5:75:0b:b7:53:e4:a5:2b:dd:ce:bd:1c:3a:7a:

                   c3:f7:13:8f:26:54:9c:16:6b:6b:af:fb:d8:96:b1:

                    60:9a:48:e0:25:22:24:79:34:ce:0e:26:00:0b:4e:

                   ab:fd:8b:ce:82:d7:2f:08:70:68:c1:a8:0a:f9:74:

                   4f:07:ab:a4:f9:e2:83:7e:27:73:74:3e:b8:f9:38:

                   42:fc:a5:a8:5b:48:23:b3:eb:e3:25:b2:80:ae:96:

                    d4:0a:9c:c2:78:9a:c6:68:18:ae:37:62:37:5e:51:

                   75:a8:58:63:c0:51:ee:40:78:7e:a8:af:1a:a0:e1:

                   b0:78:9d:50:8c:7b:e7:b3:fc:8e:23:b0:db:65:00:

                   70:84:01:08:00:14:6e:54:86:9a:ba:cc:f9:37:10:

                   f6:e0:de:84:2d:9d:a4:85:37:d3:87:e3:15:d0:c1:

                   17:90:7e:19:21:6a:12:a9:76:fd:12:02:e9:4f:21:

                    5e:17

                Exponent: 65537 (0x10001)

        X509v3 extensions:

            X509v3 BasicConstraints: critical

                CA:TRUE

            X509v3Certificate Policies:

                Policy:2.16.840.1.114171.903.1.11

                  CPS:http://www.wellsfargo.com/certpolicy

 

    Signature Algorithm: sha1WithRSAEncryption  #數字簽名,以后再講

        d2:27:dd:9c:0a:77:2b:bb:22:f2:02:b5:4a:4a:91:f9:d1:2d:

        be:e4:bb:1a:68:ef:0e:a4:00:e9:ee:e7:ef:ee:f6:f9:e5:74:

        a4:c2:d8:52:58:c4:74:fb:ce:6b:b5:3b:29:79:18:5a:ef:9b:

        ed:1f:6b:36:ee:48:25:25:14:b6:56:a2:10:e8:ee:a7:7f:d0:

        3f:a3:d0:c3:5d:26:ee:07:cc:c3:c1:24:21:87:1e:df:2a:12:

        53:6f:41:16:e7:ed:ae:94:fa:8c:72:fa:13:47:f0:3c:7e:ae:

        7d:11:3a:13:ec:ed:fa:6f:72:64:7b:9d:7d:7f:26:fd:7a:fb:

        25:ad:ea:3e:29:7f:4c:e3:00:57:32:b0:b3:e9:ed:53:17:d9:

        8b:b2:14:0e:30:e8:e5:d5:13:c6:64:af:c4:00:d5:d8:58:24:

        fc:f5:8f:ec:f1:c7:7d:a5:db:0f:27:d1:c6:f2:40:88:e6:1f:

        f6:61:a8:f4:42:c8:b9:37:d3:a9:be:2c:56:78:c2:72:9b:59:

        5d:35:40:8a:e8:4e:63:1a:b6:e9:20:6a:51:e2:ce:a4:90:df:

        76:70:99:5c:70:43:4d:b7:b6:a7:19:64:4e:92:b7:c5:91:3c:

        7f:48:16:65:7b:16:fd:cb:fc:fb:d9:d5:d6:4f:21:65:3b:4a:

         7f:47:a3:fb

SHA1 Fingerprint=93:E6:AB:22:03:03:B5:23:28:DC:DA:56:9E:BA:E4:D1:D1:CC:FB:65

關于證書文件,還有1些容易混淆的事情要交代:

  • 前面講過,證書有很多格式,但是目前通用格式為X.509格式。在上面的證書文件中,從Certificate這1行開始到文件最后,都是符合X.509格式的。那文件前面的“-----BEGINCERTIFICATE-----”到“-----END CERTIFICATE-----”是些甚么?
  • X.509是證書的格式,但是證書和我們看到的文件還是有1些差異。證書需要封裝在文件里。不同系統支持不同的證書文件,每種證書文件,所要求包括的具體的X.509證書內容也不1樣。另外,某些證書文件還能包括除X.509以外的其他有用的數據。

下面是1些常見的證書文件格式,1般用文件后綴名標示。

  • .pem(Privacy-enhanced ElectronicMail) Base64 編碼的證書,編碼信息(行將示例中X.509證書的明文內容用Base64編碼后得到的那個字符串)放在"-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----"之間。所以,Android平臺里的根CA文件都是PEM證書文件。
  • .cer,.crt, .der:證書內容為ASCII編碼,2進制格式,但也能夠和PEM1樣采取base64編碼。
  • .p7b,.p7c
    生活不易,碼農辛苦
    如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
    程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国美女福利视频午夜精品 | 伊人网站在线观看 | 成人卡通精品卡通动漫第一页 | 日本a v 黄| 欧美三级超在线视频 | 羞羞动漫免费看 | 亚洲欧洲精品久久 | 欧美日本一| 国产最新进精品视频 | 樱花aⅴ一区二区三区四区 影视精品网站入口 | 老司机午夜精品 | 第一福利视频网 | 春色视频www免费视频观看 | 成人娱乐网站 | 91成人免费福利网站在线 | 亚欧成人在线 | 亚洲精品国产综合久久一线 | 欧美日韩中文国产一区二区三区 | 一级a性色生活片毛片 | 高清在线一区二区三区亚洲综合 | 国产欧美另类 | xx小视频 | 欧美激情在线精品video | 99久久精品男女性高爱 | 级毛片久久久毛片精品毛片 | 一级做a爱片性色毛片武则天五则 | 成人国产片 | 久久久久久久久久久96av | 成人影院www在线观看 | 一级毛片不卡片免费观看 | 亚洲一二四区性毛片1在线 亚洲一个色 | 国产精品性 | 精品久久久久久中文字幕一区 | 亚洲天堂精品在线 | 日本xxxxx久色视频在线观看 | 欧美一级毛片欧美一级 | 一区二区三区四区无限乱码在线观看 | 日韩一本二本 | 国产一区二区三区视频在线观看 | 波多野结衣免费视频观看 | 一区视频 |