<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-17  評(píng)論-6  文章-1  trackbacks-0

    2004-05-29 17:39:53

    主題: 使用Java實(shí)現(xiàn)CA(四)

        前面幾篇文章已經(jīng)把如何用Java實(shí)現(xiàn)一個(gè)CA基本上講完了.但是他們都有一個(gè)特點(diǎn),就是用戶的信息都是在現(xiàn)場(chǎng)獲取的,不能做申請(qǐng)和簽發(fā)相分離.今天我們要講述的是PKCS#10證書請(qǐng)求文件.它的作用就是可以使申請(qǐng)和簽發(fā)相分離.

        PKCS#10證書請(qǐng)求結(jié)構(gòu)中的主要信息包含了被簽發(fā)者(證書申請(qǐng)者)的主體名稱(DN)和他的公鑰.因此一個(gè)CA在獲取到一個(gè)PKCS#10證書請(qǐng)求后,就可以從中獲取到任何和簽發(fā)證書有關(guān)的信息,然后用它自己的私鑰簽發(fā)證書.

        使用BC Provider在Java中構(gòu)造一個(gè)證書請(qǐng)求格式的對(duì)象調(diào)用其構(gòu)造函數(shù)即可,這個(gè)函數(shù)如下:

        PKCS10CertificationRequest(java.lang.String signatureAlgorithm, X509Name subject, java.security.PublicKey key, ASN1Set attributes, java.security.PrivateKey signingKey)

        它的參數(shù)是自簽名算法,證書申請(qǐng)者的DN,證書申請(qǐng)者的公鑰,額外的屬性集(就是要申請(qǐng)的證書的擴(kuò)展信息),申請(qǐng)證書者的私鑰.申請(qǐng)證書者的私鑰僅僅是用來進(jìn)行一下自簽名,并不出現(xiàn)在證書請(qǐng)求中,需要自簽名的目的是保證該公鑰確實(shí)為申請(qǐng)者所有.

        調(diào)用該對(duì)象的getEncoded()方法可以將其進(jìn)行DER編碼,然后儲(chǔ)存起來,該對(duì)象還有另一個(gè)構(gòu)造函數(shù):
        PKCS10CertificationRequest(byte[] bytes)
        這個(gè)構(gòu)造函數(shù)的作用就是直接從儲(chǔ)存的DER編碼中把這個(gè)對(duì)象還原出來.

        利用證書請(qǐng)求結(jié)構(gòu)進(jìn)行證書簽發(fā)的代碼如下,這里假設(shè)CSR是一個(gè)已經(jīng)獲取出來的PKCS10CertificationRequest結(jié)構(gòu):

        PublicKey SubjectPublicKey = CSR.getPublicKey();
        CertificationRequestInfo CSRInfo = CSR.getCertificationRequestInfo();
        X509Name SubjectDN = CSRInfo.getSubject();
        ASN1Set Attributes = CSRInfo.getAttributes();

        這樣,申請(qǐng)者的主體DN,申請(qǐng)者的公鑰,申請(qǐng)者希望在證書擴(kuò)展信息中填寫的屬性都得到了,剩下的事情就和用戶在現(xiàn)場(chǎng)輸入時(shí)一樣了,其它的信息一般是申請(qǐng)者不能決定的.另外證書請(qǐng)求格式中有一樣信息沒有明確給出來,那就是證書的有效期,這個(gè)應(yīng)該單獨(dú)詢問用戶,或者用其它的方法保存起來.



    [返回頂部]


    2004-05-28 16:46:12

    主題: 使用Java實(shí)現(xiàn)CA(三)

        前幾次我已經(jīng)基本上把如何做CA所需要的基礎(chǔ)知識(shí)講得差不多了,今天直接講如何用Java程序來實(shí)現(xiàn)一個(gè)CA應(yīng)該就不是什么太困難的事情了.

        要做CA,第一步要準(zhǔn)備好自己的證書和私鑰.私鑰如何從文件里面讀取出來前面已經(jīng)講過了.從文件系統(tǒng)中讀出證書的代碼如下:

        CertificateFactory certCF = CertificateFactory.getInstance("X.509");
        X509Certificate caCert = certCF.generateCertificate(certBIS);

        這里cerBIS是一個(gè)InputStream類型的對(duì)象.例如一個(gè)標(biāo)準(zhǔn)的X509v3格式的證書文件所形成的輸入流.

        第二步就是從用戶那里獲取輸入,然后構(gòu)造主體名稱結(jié)構(gòu)DN,如何構(gòu)造DN上次已經(jīng)說過了,如何從用戶那里獲取輸入,這個(gè)不在本文討論范圍之內(nèi).

        下一步就是獲取用戶的公鑰,好和他所需要的證書對(duì)應(yīng)起來.也有不少CA的做法就是在這里替用戶現(xiàn)場(chǎng)生成一對(duì)密鑰對(duì),然后把公鑰放到證書中簽發(fā)給用戶.這個(gè)應(yīng)該看實(shí)際需要選擇合適的方式.

        現(xiàn)在一切信息都已經(jīng)準(zhǔn)備好了,可以簽發(fā)證書了,下面的代碼說明了這個(gè)過程:

        //構(gòu)造一個(gè)證書生成器對(duì)象

        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

        // 從CA的證書中獲取簽發(fā)者的主體名稱(DN)
        // 這里有一點(diǎn)小技巧,我們要把JCE中定義的
        // 用來表示DN的對(duì)象X500Principal轉(zhuǎn)化成在
        // BC Provider中的相應(yīng)的對(duì)象X509Name
        // 先從CA的證書中讀取出CA的DN進(jìn)行DER編碼
        DERInputStream dnStream =
                     new DERInputStream(
          new ByteArrayInputStream(
           caCert.getSubjectX500Principal().
            getEncoded()));
        // 馬上又從編碼后的字節(jié)流中讀取DER編碼對(duì)象
        DERConstructedSequence  dnSequence =
         (DERConstructedSequence)dnStream.readObject();
        // 利用讀取出來的DER編碼對(duì)象創(chuàng)建X509Name
        // 對(duì)象,并設(shè)置為證書生成器中的"簽發(fā)者DN"
        certGen.setIssuerDN(new X509Name(dnSequence));
        // 設(shè)置好證書生成器中的"接收方DN"
        certGen.setSubjectDN(subjectDN);
        // 設(shè)置好一些擴(kuò)展字段,包括簽發(fā)者和
        // 接收者的公鑰標(biāo)識(shí)
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
        createSubjectKeyId(keyToCertify));
        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
        createAuthorityKeyId(caCert.getPublicKey()));
        // 設(shè)置證書的有效期和序列號(hào)
        certGen.setNotBefore(startDate);
        certGen.setNotAfter(endDate);
        certGen.setSerialNumber(serialNumber);
        // 設(shè)置簽名算法,本例中使用MD5hash后RSA
        // 簽名,并且設(shè)置好主體的公鑰
        certGen.setSignatureAlgorithm("MD5withRSA");
        certGen.setPublicKey(keyToCertify);

        // 如果以上一切都正常地話,就可以生成證書了
        X509Certificate cert = null;
        cert = certGen.generateX509Certificate(caPrivateKey);

        這里是上面用到的生成簽發(fā)者公鑰標(biāo)識(shí)的函數(shù): 

        protected AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pubKey)
        {
        AuthorityKeyIdentifier authKeyId = null;

        try
        {
        ByteArrayInputStream bIn = new ByteArrayInputStream(pubKey.getEncoded());
        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
            (DERConstructedSequence)new DERInputStream(bIn).readObject());
        authKeyId = new AuthorityKeyIdentifier(info);
        }
        catch (IOException e)
        {
        System.err.println("Error generating SubjectKeyIdentifier:  " +
            e.toString());
        System.exit(1);
        }

        return authKeyId;
        }

        生成主體公鑰標(biāo)識(shí)的函數(shù)和上面的類似,把AuthorityKeyIdentifier替換成SubjectKeyIdentifier就可以了.

        這里要注意的是,CA的公鑰也是在一份證書里,這種證書的特點(diǎn)是簽發(fā)者DN和接收者DN一樣,也就是說,這種證書是CA自己給自己頒發(fā)的證書,也就是"自簽名證書",它上面的公鑰是CA自身的公鑰,用來簽名的私鑰就是該公鑰對(duì)應(yīng)的私鑰.一般每個(gè)CA都要有這么一份證書,除非該CA不是根CA,即它的權(quán)威性不是由它自己證明,而是由它的上級(jí)CA證明.但是,最后總歸要有一個(gè)根CA,它為各個(gè)安全應(yīng)用程序的用戶所信賴.

        到這里我們已經(jīng)把CA最基本的功能如何用Java實(shí)現(xiàn)講完了,下一次講如何從PKCS#10格式證書請(qǐng)求文件中讀取出用戶信息,然后直接簽發(fā)公鑰.



    [返回頂部]


    2004-05-27 15:34:59

    主題: 使用Java實(shí)現(xiàn)CA(二)

        昨天本來快寫完了,結(jié)果不小心按了"tab"鍵,然后向按退格鍵,結(jié)果退到前一個(gè)頁面了,然后全部都白寫了,不爽.只好今天重新寫了.

        上次我們講到如何生成密鑰對(duì),以及如何將諸如公鑰,私鑰,證書等這一類安全對(duì)象在文件系統(tǒng)和內(nèi)存之間來回轉(zhuǎn)換.這些是準(zhǔn)備開CA的基本功,今天我們講一下CA的基本原理以及如何使用主體名稱結(jié)構(gòu)DN(Distinguish Name)來表示每一個(gè)證書中的主體.

        一份證書就是一個(gè)權(quán)威機(jī)構(gòu)對(duì)一個(gè)主體的身份的確認(rèn)的證明.即一份證書表示一個(gè)權(quán)威機(jī)構(gòu)確認(rèn)了一個(gè)主體就是它自己,而不是其它的冒名頂替者.主體可以是一個(gè)個(gè)人,也可以不是,例如,在需要安全服務(wù)的時(shí)候,需要為一臺(tái)網(wǎng)站的服務(wù)器頒發(fā)證書,這種證書的主體就是一臺(tái)服務(wù)器.簽署證書的權(quán)威機(jī)構(gòu)就叫做CA,該權(quán)威機(jī)構(gòu)本身也是一個(gè)主體.權(quán)威機(jī)構(gòu)通過對(duì)包含有待認(rèn)證的主體的一系列信息的待簽名證書"(TBS,to be signed)進(jìn)行數(shù)字簽名來表示該機(jī)構(gòu)對(duì)它的認(rèn)可.一份包含了待認(rèn)證的主體的相關(guān)信息的TBS再加上CA使用自己的私鑰進(jìn)行簽名產(chǎn)生的字節(jié)流放在一起,就構(gòu)成了一份標(biāo)準(zhǔn)的X509證書.

        一個(gè)TBS中包含了以下這些主要信息:

        證書的版本,通常是3(X509v3)

        證書的序列號(hào),RFC3280中規(guī)定,每個(gè)CA必須確保它頒發(fā)的每一份證書的序列號(hào)都是唯一的,并且序列號(hào)只能使用非負(fù)整數(shù).

        簽發(fā)者(CA)的主體名稱,一個(gè)DN對(duì)象.

        證書的有效期,表示方法是兩個(gè)時(shí)間值,表示了該證書從何時(shí)開始生效,何時(shí)開始作廢.

        待認(rèn)證的主體的主體名稱,也是一個(gè)DN對(duì)象.

        待認(rèn)證的主體的公鑰,任何安全應(yīng)用在確認(rèn)完證書的有效性后,就可以開始使用該主體的公鑰與之進(jìn)行安全通信.

        如果是X509v3證書,即版本號(hào)是3的話,后面還有一個(gè)證書擴(kuò)展信息字段,可以在證書里面添加一些其它的信息.

        下面我們來看一下表示主體的主體名稱結(jié)構(gòu):DN.這個(gè)結(jié)就構(gòu)是一個(gè)屬性的集合.每個(gè)屬性有屬性名稱和屬性值.它的作用就是用來表示"我是誰",也就是說,這個(gè)證書到底是誰頒發(fā)給誰的,這個(gè)證書對(duì)應(yīng)的公鑰是誰擁有的.

        通常使用一個(gè)字符串來表示DN結(jié)構(gòu),這種字符串說明了這種結(jié)構(gòu)中的各個(gè)屬性的類型和值:

        C=CN;S=BeiJing;L=BeiJing;O=PKU;OU=ICST;CN=wolfenstein

        這里C是國家和地區(qū)代碼,S和L都是地區(qū)代碼,S相當(dāng)于省或者州這樣的級(jí)別,L相當(dāng)于城市級(jí)別,O是組織機(jī)構(gòu)名稱,OU是次級(jí)組織機(jī)構(gòu)名稱,CN是主體的通用名(common name).在這里,C,S,L等等屬性的類型都是相對(duì)固定的,例如C一般就是用來表示國家和地區(qū)代碼,在DN結(jié)構(gòu)中還可以添加一些其它類型的信息,一般也都是以"xxx=xxx"這樣來表示的.

        下面我們來說明如何在Java語言中構(gòu)造出一個(gè)主體名稱對(duì)象.

        BC Provider中使用X509Name對(duì)象來表示DN,構(gòu)造一個(gè)X509Name的步驟大體如下:

        先構(gòu)造兩個(gè)vector對(duì)象,用來表示屬性名稱和屬性值:

        Vector oids = new Vector();
        Vector attributes = new Vector();

        然后在oids這個(gè)用來表示屬性名稱的vector對(duì)象中將屬性名稱一個(gè)一個(gè)添加進(jìn)去:

        oids.addElement(X509Name.C);

        ......

        oids.addElement(X509Name.CN);

        X509Name對(duì)象里面有若干常量,例如上面的X509Name.C.還有X509Name.ST等等,都可以和上面舉的例子對(duì)應(yīng)起來.

        然后將屬性值添加到attributes對(duì)象中:

        attributes.addElement("CN");

        ......

        attributes.addElement("Wolfenstein");

        最后就可以構(gòu)造出一個(gè)X509Name對(duì)象:

        X509Name SubjectDN = new X509Name(oids, attributes);

        這樣,我們的主體名稱結(jié)構(gòu)就確立起來了.

        下次我們就可以講關(guān)鍵的部分了,那就是如何用Java程序完成CA最重要的功能,簽署證書.



    [返回頂部]


    2004-05-25 21:23:52

    主題: 使用Java實(shí)現(xiàn)CA(一)

        通過我昨天的文章大家應(yīng)該已經(jīng)清楚了,用Java寫信息安全方面的程序需要做的準(zhǔn)備工作.好了,現(xiàn)在假設(shè)你已經(jīng)是一個(gè)對(duì)Java語言本身比較熟悉,能夠用Java寫一些程序的人,并且這些該下載的jar包已經(jīng)下載好了,可以正式開工了.

        在所有的此類程序的開頭(無論是在類的構(gòu)造函數(shù)中也好,在初始化函數(shù)中也好),都要先來上這么一句:Security.addProvider(new BouncyCastleProvider());將BouncyCaslte的Provider添加到系統(tǒng)中,這樣以后系統(tǒng)在運(yùn)行相關(guān)程序的時(shí)候調(diào)用的就是這個(gè)Provider中的加密算法.

        然后我們就可以開始開CA了.首先,作為一個(gè)CA要有自己的一對(duì)公鑰和私鑰,我們先要生成這么一對(duì).使用KeyPairGenerator對(duì)象就可以了,調(diào)用KeyPairGenerator.getInstance方法可以根據(jù)要生成的密鑰類型來產(chǎn)生一個(gè)合適的實(shí)例,例如常用的RSA,DSA等.然后調(diào)用該對(duì)象的initialize方法和generateKeyPair方法就可以產(chǎn)生一個(gè)KeyPair對(duì)象了.然后調(diào)用KeyPair對(duì)象中的相應(yīng)方法就可以獲取生成的密鑰對(duì)中的公鑰和私鑰了.

        有了公鑰和私鑰對(duì)以后,下面的一個(gè)很現(xiàn)實(shí)問題就是如何把它們儲(chǔ)存起來.通常我們要對(duì)這些安全對(duì)象,如公鑰,私鑰,證書等先進(jìn)行編碼.編碼的目的是為了把結(jié)構(gòu)復(fù)雜的安全對(duì)象變成字節(jié)流以便存儲(chǔ)和讀取,如DER編碼.另外,通常還把DER編碼后的字節(jié)流再次進(jìn)行base64編碼,以便使字節(jié)流中所有的字節(jié)都變成可打印的字節(jié).

        在Java語言中,這些安全對(duì)象基本上都有g(shù)etEncoded()方法.例如:

        byte[] keyBytes = privateKey.getEncoded();

        這樣就把一個(gè)私鑰進(jìn)行了DER編碼后的結(jié)果保存到一個(gè)byte數(shù)組中了.然后就可以把這個(gè)byte數(shù)組保存到任何介質(zhì)中.如果有必要的話,可以使用BC Provider中的Base64編碼解碼器類進(jìn)行編碼,就像這樣:

        byte data[] = Base64.encode(keyBytes);

        要從文件中讀取私鑰則應(yīng)該這樣:

        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyData);
        KeyFactory kfac = KeyFactory.getInstance("RSA");
        privateKey = kfac.generatePrivate(spec);

        這里說明一下,對(duì)RSA私鑰進(jìn)行編碼就會(huì)自動(dòng)地按照PKCS8進(jìn)行.因此讀取的時(shí)候?qū)幋a的字節(jié)數(shù)組作為PKCS8EncodedKeySpec對(duì)象的構(gòu)造函數(shù)的參數(shù)就可以生成一個(gè)該類型的對(duì)象.然后創(chuàng)建一個(gè)密鑰工廠對(duì)象就可以按照要求生成一個(gè)RSA私鑰了.很顯然這里的keyData應(yīng)該是和上面的keyBytes內(nèi)容相同.

        為了提高系統(tǒng)的安全性,通常私鑰在經(jīng)過DER編碼后,還會(huì)使用一個(gè)口令進(jìn)行加密,然后再儲(chǔ)存在文件系統(tǒng)中.在使用私鑰的時(shí)候,如果沒有正確的口令,是無法把私鑰還原出來的.

        保存證書和保存私鑰類似.Certificate對(duì)象中也有一個(gè)getEncoded的方法.

        這次就講這些.大家應(yīng)該可以把這些安全對(duì)象很熟練地從文件系統(tǒng)和內(nèi)存之間來回地折騰了吧.這對(duì)以后實(shí)現(xiàn)CA是很重要的.下次我會(huì)講一下證書中表示主體的方法:DN.



    [返回頂部]


    2004-05-24 17:23:06

    主題: 使用Java開發(fā)和信息安全相關(guān)的程序

        這里說的信息安全是相對(duì)于系統(tǒng)安全而言的,它更側(cè)重于加密,解密,數(shù)字簽名,驗(yàn)證,證書等等.而系統(tǒng)安全主要側(cè)重于系統(tǒng)本身是否有安全漏洞,如常見的由于軟件設(shè)計(jì)的不完善而導(dǎo)致的滿天飛的緩沖區(qū)溢出等等.

        Java語言中負(fù)責(zé)加密功能的部件是JCE(Java Crypto Extenstion),它使用開放式的思想,可以允許用戶自己編寫加密算法的具體實(shí)現(xiàn)的模塊等.這些東西被稱為JCE Provider,JCE的提供者.SUN公司本身提供了一些Provider.不過我推薦使用Bouncy Castle的Provider.原因是它實(shí)現(xiàn)的加密算法多,連比較新的橢圓曲線(ECC)算法都有了.去http://www.bouncycastle.org/可以找到你所希望的.Bouncy Castle除了提供Provider本身以外,還包括了一個(gè)S/MIME和一個(gè)open pgp 的jar包只有Provider本身是必要的,后兩個(gè)包是方便你編程而提供的.例如有了S/MIME包后,你就不再需要為諸如"加密一個(gè)字符串或者一片文章然后簽名"之類的很現(xiàn)實(shí)的應(yīng)用程序?qū)懮弦淮蠖汛a了,只要引用S/MIME包中的某幾個(gè)類,很快就可以搞定.而open pgp的存在,使你在用Java編寫和PGP/GPG交互的程序時(shí)方便多了.

        這次先寫這么多了,下次開始具體講把這些東西搞下來后怎么開始干活吧.我以我現(xiàn)在手頭上正在做的事情告訴大家,如何做一個(gè)CA.

        有了BC Provider,開CA,真的就是這么簡單!

    posted on 2006-02-20 11:07 小鐵匠 閱讀(6121) 評(píng)論(0)  編輯  收藏 所屬分類: java
    主站蜘蛛池模板: 亚洲国产精品成人久久| 亚洲人成免费电影| 1000部拍拍拍18勿入免费视频软件 | 18观看免费永久视频| 久久精品国产亚洲AV蜜臀色欲 | 国产精品青草视频免费播放| 亚洲AV日韩AV天堂一区二区三区| 国产在线观看片a免费观看| 免费很黄无遮挡的视频毛片| 亚洲资源在线观看| 日本高清免费不卡视频| 99久久国产热无码精品免费| 婷婷国产偷v国产偷v亚洲| 亚洲AV无码成人精品区在线观看 | 亚洲激情在线视频| 国产精品二区三区免费播放心| 中文字幕无码免费久久| 国产亚洲中文日本不卡二区| 久久精品国产亚洲一区二区| 最新免费jlzzjlzz在线播放| a级毛片视频免费观看| 亚洲欧美黑人猛交群| 久热综合在线亚洲精品| 国产一区在线观看免费| 2021在线永久免费视频| 精品97国产免费人成视频| 亚洲kkk4444在线观看| 亚洲天天做日日做天天看| 亚洲综合久久夜AV | 天天拍拍天天爽免费视频| 久久精品一区二区免费看| 日韩精品无码免费视频| 中国china体内裑精亚洲日本| 亚洲人成在线影院| 黑人大战亚洲人精品一区| 国产三级免费电影| 成人免费无码大片a毛片| 亚洲一区在线免费观看| A级毛片高清免费视频在线播放| 蜜臀亚洲AV无码精品国产午夜.| 亚洲人成人77777网站不卡|