一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

2023-11-26 01:15未知服務(wù)器之家 Java教程

"Almost no one will remember what he had just not interested." - Nobody “幾乎沒有人會記得他所絲毫不感興趣的事情。” —— 佚名 0x00 大綱 目錄 0x00 大綱 0x01 前言 0x02 技術(shù)選型 0x03 需求分析 目標(biāo)用戶 用戶故事 功能需求 安全需求 兼容需求 性能

"Almost no one will remember what he had just not interested." - Nobody

“幾乎沒有人會記得他所絲毫不感興趣的事情。” —— 佚名

0x00 大綱

目錄
  • 0x00 大綱
  • 0x01 前言
  • 0x02 技術(shù)選型
  • 0x03 需求分析
    • 目標(biāo)用戶
    • 用戶故事
    • 功能需求
    • 安全需求
    • 兼容需求
    • 性能需求
  • 0x04 原型設(shè)計(jì)
    • 主窗體
    • RSA根證書生成頁面
    • ECC根證書生成頁面
    • RSA證書生成頁面
    • ECC證書生成頁面
  • 0x05 架構(gòu)設(shè)計(jì)
  • 0x06 概要設(shè)計(jì)
  • 0x07 詳細(xì)設(shè)計(jì)
  • 0x08 編碼實(shí)現(xiàn)
    • RSA根證書生成(節(jié)選關(guān)鍵部分)
    • ECC根證書生成
  • 0x09 小結(jié)
    • 運(yùn)行效果

0x01 前言

隨著這些年人們對于信息安全的愈加重視,工作中經(jīng)常用到各種數(shù)字證書,最主要的用途就是加密和簽名。但是反復(fù)生成用于測試的數(shù)字證書是一件麻煩事,雖然感謝有強(qiáng)大的OpenSSL工具,但是問就是記不住命令,問就是不想看文檔。為了提高工作效率,降低苦痛指數(shù),遂決定開發(fā)一個(gè)證書生成小工具。

0x02 技術(shù)選型

我們需要一個(gè)簡單的GUI,在Java的領(lǐng)域中,可以選擇使用JavaFX或著Swing來實(shí)現(xiàn),鑒于我們不需要太花哨的東西,只需要幾個(gè)簡單的布局和控件,這里選擇了使用Swing來開發(fā)圖形界面。小聲BB:甲方是我,乙方也是我,能用就行,要啥自行車。

我們需要用到RSA或著國密的數(shù)字證書,湊巧BouncyCastle就是一個(gè)提供了很多哈希算法和加密算法的第三方庫。老牌子,易使用。

初步估計(jì)工期為一周,太長容易從入門到放棄,太短則對心臟不友好。

0x03 需求分析

目標(biāo)用戶

  • 給開發(fā)人員用
  • 給業(yè)務(wù)人員用
  • 給測試人員用

用戶故事

作為使用者:

  • 我需要工具同時(shí)支持生成RSA和國密的證書;
  • 我想簡單點(diǎn)幾下按鈕就能生成自己想要的證書,我不想記一大串又臭又長的命令行;
  • 我不希望到處搜索一堆奇奇怪怪的參數(shù),最好什么都不用我填,什么都不用我自己思考;
  • 什么YES or NO統(tǒng)統(tǒng)不要,問就是YES......
  • 我希望你界面盡量不要太花哨,時(shí)間長了看的我眼花;
  • 最好支持批量操作,免得折了我鼠標(biāo)的壽。

功能需求

  • 使用GUI操作的小工具,包含四個(gè)功能菜單:
    • RSA根證書生成
    • RSA證書生成
    • ECC根證書生成,支持批量操作;
    • ECC證書生成,支持批量操作;
    • 生成的同時(shí)通過文件選擇對話框選擇保存路徑;
  • RSA根證書簽發(fā):
    • 可以根據(jù)選定的密鑰算法和簽名算法,生成RSA和國密的非對稱密鑰對,默認(rèn)使用123456對私鑰進(jìn)行加密,可指定密碼,也可一鍵生成隨機(jī)密碼;
    • 證書
    • 對于同一對密鑰,需要同時(shí)導(dǎo)出:
      • DER編碼的PKCS#8加密私鑰,文件后綴名為.key;
      • PEM編碼的PKCS#8加密私鑰,文件后綴名為.pri.pem;
      • PEM編碼的X.509公鑰,文件后綴名為.pub.pem;
      • DER編碼的X.509公鑰,文件后綴名為.cer;
      • 同時(shí)包含X.509公鑰和PKCS#8加密私鑰的PKCS#12證書,文件后綴名為.pfx;
      • 包含私鑰密碼的文本文件,文件后綴為.txt;
        以上文件在一個(gè)壓縮包中打包導(dǎo)出,壓縮文件后綴為.zip;
  • RSA證書簽發(fā):
    • 使用選定的根證書,簽發(fā)中間證書或葉子證書;
    • 導(dǎo)出要求同上;
  • ECC證書簽發(fā):
    • 同RSA根證書簽發(fā);
  • ECC證書簽發(fā):
    • 使用國密sm2p256v1曲線,其余同RSA證書簽發(fā);
  • 對于RSA證書,擬支持2048(首選)、1024、4096密鑰位數(shù),支持SHA1withRSA、SHA256withRSA、MD5withRSA簽名算法;
  • 對于ECC證書,擬支持sm2p256v1曲線,支持SM3withSM2、SHA256withSM2簽名算法;
  • 證書頒發(fā)者信息至少包含:
    • country code (C)
    • locality name (L)
    • state/province name (ST)
    • organization (O)
    • common name (CN)
    • organizational unit name (OU)
      最好都有默認(rèn)值,能不填就盡量不要填,免得浪費(fèi)我喝咖啡的時(shí)間;
  • 證書使用者信息默認(rèn)同頒發(fā)者信息;
  • 證書有效期默認(rèn)十年(部分系統(tǒng)不允許過長的證書有效期,第一個(gè)版本不考慮這么多);

安全需求

略,見功能需求加密部分。

兼容需求

應(yīng)與操作系統(tǒng)和其他軟硬加密機(jī)生成的證書互相兼容。

性能需求

能用就行。

0x04 原型設(shè)計(jì)

有了大體上的功能需求分析,就可以進(jìn)入設(shè)計(jì)階段了,既然是GUI程序,那就先從界面入手,簡單做一下原型。正好idea上帶有Swing UI Designer,所見即所得,原型可以直接轉(zhuǎn)化為后期工程。

主窗體

使用JTabbedPane作為容器,承載四個(gè)主要功能菜單,簡化交互設(shè)計(jì)。再加上四個(gè)功能界面功能上高度相似,也意味著GUI元素的高度相似,只要設(shè)計(jì)出一個(gè),其他幾個(gè)直接Ctrl+C,Ctrl+V即可。

為了減少動態(tài)窗體大小帶來的布局調(diào)整和元素Resize,直接使用固定大小窗體,初步定為 640*560 像素。

RSA根證書生成頁面

大部分GUI元素都是按鈕(JButton),下拉框(JComboBox)和輸入框(JTextField or JPasswordField),因此可以考慮左邊為標(biāo)簽(JLabel),右邊為交互元素的表單結(jié)構(gòu),首選布局即為Grid Layout。剩下的就是往JPanel上扔控件了。經(jīng)過一番努力,我們得到了這樣的窗體設(shè)計(jì):

基于Java Swing和BouncyCastle的證書生成工具

于是通過復(fù)制粘貼,很快可以完成剩余的三個(gè)界面:

ECC根證書生成頁面

基于Java Swing和BouncyCastle的證書生成工具

RSA證書生成頁面

基于Java Swing和BouncyCastle的證書生成工具

ECC證書生成頁面

基于Java Swing和BouncyCastle的證書生成工具

0x05 架構(gòu)設(shè)計(jì)

由于證書生成工具的定位是C端程序,區(qū)別于B/S模型的應(yīng)用,它更適合使用傳統(tǒng)老三層模型(USL、BLL、DAL),而不是Web應(yīng)用上經(jīng)常使用的MVC分層模式。

通過前面的原型設(shè)計(jì),已經(jīng)基本完成了USL表示層中的視圖部分,接下來需要實(shí)現(xiàn)USL的控制部分和BLL層的業(yè)務(wù)邏輯(其實(shí)就是實(shí)現(xiàn)各個(gè)控件需要關(guān)注的事件監(jiān)聽以及對應(yīng)的事件處理),由于我們的數(shù)據(jù)持久方式就是文件,所以數(shù)據(jù)訪問層反而比較簡單了。

DAL層雖然簡單,但是我們保持開放修改的后路,萬一哪天要用數(shù)據(jù)庫呢?嘿嘿~

0x06 概要設(shè)計(jì)

通過需求分析和原型設(shè)計(jì)已經(jīng)大致可以劃分出功能模塊了,核心部分就是幾個(gè)按鈕的事件監(jiān)聽和處理。

它們都可以統(tǒng)合到一個(gè)流程模型中:

參數(shù)錄入->點(diǎn)擊按鈕->獲取參數(shù)->驗(yàn)證參數(shù)->生成數(shù)據(jù)->更新UI

以生成RSA根證書處理流程為例:

  1. 參數(shù)錄入:界面上選擇密鑰位數(shù)、簽名算法、證書密碼(可選)、證書頒發(fā)者信息(可選);
  2. 點(diǎn)擊按鈕:監(jiān)聽按鈕點(diǎn)擊事件;
  3. 獲取參數(shù):獲取UI和后臺的相關(guān)參數(shù);
  4. 驗(yàn)證參數(shù):進(jìn)行參數(shù)合法性檢查,包括但不限于長度,格式,關(guān)聯(lián)性等;
  5. 生成數(shù)據(jù):根據(jù)參數(shù),調(diào)用BouncyCastle庫生成RSA密鑰對;適配和打包輸出壓縮文件;
  6. 更新UI:提示生成結(jié)果,選擇文件存儲路徑等;

異常處理:

  1. 界面彈出提示框;
  2. 后臺記錄日志等;

0x07 詳細(xì)設(shè)計(jì)

將主業(yè)務(wù)流程的各個(gè)節(jié)點(diǎn)展開并詳細(xì)描述其實(shí)現(xiàn),必要時(shí)借助偽代碼進(jìn)行邏輯表示;這里就不寫了,問就是懶……

0x08 編碼實(shí)現(xiàn)

RSA根證書生成(節(jié)選關(guān)鍵部分)

public final class RSA {
    public static final String MD5_WITH_RSA = "MD5withRSA";
    public static final String SHA1_WITH_RSA = "SHA1withRSA";
    public static final String SHA256_WITH_RSA = "SHA256withRSA";
    public static final int KEY_SIZE_1024 = 1024;
    public static final int KEY_SIZE_2048 = 2048;
    public static final int KEY_SIZE_4096 = 4096;

    private RSA() {
    }

    public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
        if ((keySize & keySize - 1) != 0) {
            throw new InvalidParameterException("非法RSA密鑰位數(shù)" + keySize);
        }
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(Global.ALGO_NAME_RSA);
        keyPairGenerator.initialize(keySize);
        return keyPairGenerator.generateKeyPair();
    }
}
private ActionListener rsaRootGenerateButtonListener() {
    return e -> {
        try {
            checkRSARootCertificateConfig();
            JFileChooser fileChooser = makeSaveFileChooser();
            if (JFileChooser.APPROVE_OPTION == fileChooser.showSaveDialog(mainFrame)) {
                String saveDir = fileChooser.getSelectedFile().getAbsolutePath();
                char[] passwordChars = rsaRootPasswordField.getPassword();
                X500Name issuer = obtainIssuerEntry(rsaIssuerCField, rsaIssuerLField, rsaIssuerSTField, rsaIssuerOField, rsaIssuerCNField, rsaIssuerOUField).getValue();
                KeyPair caKeyPair = RSA.generateKeyPair(rsaRootKeySizeBox.getItemAt(rsaRootKeySizeBox.getSelectedIndex()));
                X509Certificate caCertificate = CertificateUtil.generateCertificate(rsaRootSignAlgoBox.getItemAt(rsaRootSignAlgoBox.getSelectedIndex()), caKeyPair, issuer);
                caCertificate.checkValidity(caCertificate.getNotBefore());
                caCertificate.checkValidity(caCertificate.getNotAfter());
                caCertificate.verify(caKeyPair.getPublic());
                PKCS8EncryptedPrivateKeyInfo caPrivateKeyInfo = KeyUtil.makePKCS8EncryptedKey(caKeyPair.getPrivate(), passwordChars);
                PKCS12PfxPdu caPfxPdu = KeyUtil.makePfx(caCertificate, caKeyPair.getPrivate(), passwordChars);
                saveCertificateFiles(saveDir, rsaIssuerCNField.getText(), caPrivateKeyInfo, caCertificate, caPfxPdu, passwordChars);
            }
        } catch (RuntimeException | IOException | GeneralSecurityException | OperatorCreationException | PKCSException ex) {
            JOptionPane.showMessageDialog(mainFrame, ex.getLocalizedMessage(), "錯(cuò)誤提示", JOptionPane.ERROR_MESSAGE);
        }
    };
}
public static X509Certificate generateCertificate(String signatureAlgorithm, KeyPair keyPair, X500Name subject) throws OperatorCreationException, IOExcepti
    return generateCertificate(signatureAlgorithm, keyPair, subject, Duration.ofDays(365L * 10));
}

public static X509Certificate generateCertificate(String signatureAlgorithm, KeyPair keyPair, X500Name subject, Duration duration) throws OperatorCreationE
    ContentSigner contentSigner = makeContentSigner(signatureAlgorithm, keyPair.getPrivate());
    PKCS10CertificationRequest csr = generateCsr(contentSigner, keyPair, subject, true);
    BcX509ExtensionUtils extUtils = new BcX509ExtensionUtils();
    final Date notBefore = new Date();
    X509v3CertificateBuilder v3CertificateBuilder = new X509v3CertificateBuilder(
            csr.getSubject(),
            BigInteger.valueOf(UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE),
            notBefore,
            new Date(notBefore.getTime() + duration.toMillis()),
            Locale.CHINA,
            csr.getSubject(),
            csr.getSubjectPublicKeyInfo());
    v3CertificateBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
    v3CertificateBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign));
    v3CertificateBuilder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(csr.getSubjectPublicKeyInfo()));
    v3CertificateBuilder.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(csr.getSubjectPublicKeyInfo()));
    return new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate(v3CertificateBuilder.build(contentSigner));
}
public static PKCS8EncryptedPrivateKeyInfo makePKCS8EncryptedKey(PrivateKey privateKey, char[] passwordChars) {
    PKCS8EncryptedPrivateKeyInfoBuilder privateKeyInfoBuilder = new JcaPKCS8EncryptedPrivateKeyInfoBuilder(privateKey);
    return privateKeyInfoBuilder.build(new BcPKCS12PBEOutputEncryptorBuilder(
            PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC,
            new CBCBlockCipher(new DESedeEngine())).build(passwordChars));
}

public static PKCS12PfxPdu makePfx(X509Certificate x509Certificate, PrivateKey privateKey, char[] passwordChars) throws IOException, PKCSException {
    PKCS12SafeBagBuilder certBagBuilder = new JcaPKCS12SafeBagBuilder(x509Certificate);
    certBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Forge CA Certification"));
    certBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId, ASN1Primitive.fromByteArray(x509Certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId())));
    PKCS12SafeBagBuilder keyBagBuilder = new JcaPKCS12SafeBagBuilder(privateKey,
            new BcPKCS12PBEOutputEncryptorBuilder(
                    PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC,
                    new CBCBlockCipher(new DESedeEngine())).build(passwordChars));
    keyBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Forge CA Key"));
    keyBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId, ASN1Primitive.fromByteArray(x509Certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId())));
    PKCS12PfxPduBuilder pfxPduBuilder = new PKCS12PfxPduBuilder();
    PKCS12SafeBag[] certs = new PKCS12SafeBag[1];
    certs[0] = certBagBuilder.build();
    pfxPduBuilder.addEncryptedData(new BcPKCS12PBEOutputEncryptorBuilder(
                    PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC,
                    new CBCBlockCipher(new RC2Engine())).build(passwordChars),
            certs);
    pfxPduBuilder.addData(keyBagBuilder.build());
    return pfxPduBuilder.build(new BcPKCS12MacCalculatorBuilder(), passwordChars);
}

ECC根證書生成

略,與RSA大同小異。

0x09 小結(jié)

運(yùn)行效果

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

基于Java Swing和BouncyCastle的證書生成工具

完成任務(wù)。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 好大好粗好舒服 | chinese特色video| 欧美专区在线播放 | 亚洲精品一区二区三区在线观看 | 美女被草出水 | 狠狠干2017| 欧美精品1区2区 | 久久九九亚洲精品 | 午夜爱爱爱爱爽爽爽视频网站 | 乌克兰成人性色生活片 | 婷综合 | 国产高清好大好夹受不了了 | 亚洲精品久久7777777 | 国产亚洲福利精品一区二区 | 闺蜜的样子小说安沁在线阅读 | 91传媒制片厂制作传媒破解版 | 日本久久影视 | 古代翁熄乩伦小说h | 欧美精品一线二线大片 | 无人影院在线播放 | 国产最新进精品视频 | 四虎永久免费地址在线网站 | 欧美黑人性猛交╳xx╳动态图 | 99这里精品 | 亚洲第一成年免费网站 | 亚洲琪琪 | 美女的隐私视频免费看软件 | 日本中文字幕黑人借宿影片 | 美女靠逼动漫 | 男人猛激烈吃奶gif动态图 | 91精品乱码一区二区三区 | 日韩欧美综合在线二区三区 | 成人天堂入口网站 | 国产一级毛片外aaaa | 免费精品99久久国产综合精品 | 1024免费观看完整版在线播放 | 国产专区亚洲欧美另类在线 | 国产精品永久免费10000 | 香蕉eeww99国产精选播放 | 精品国内自产拍在线视频 | 亚洲美女人黄网成人女 |