<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

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

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

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

      0x00 大綱

      0x01 前言

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

      0x02 技術選型

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

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

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

      0x03 需求分析

      目標用戶

      • 給開發人員用
      • 給業務人員用
      • 給測試人員用

      用戶故事

      作為使用者:

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

      功能需求

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

      安全需求

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

      兼容需求

      應與操作系統和其他軟硬加密機生成的證書互相兼容。

      性能需求

      能用就行。

      0x04 原型設計

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

      主窗體

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

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

      RSA根證書生成頁面

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

      UI-1

      于是通過復制粘貼,很快可以完成剩余的三個界面:

      ECC根證書生成頁面

      UI-2

      RSA證書生成頁面

      UI-3

      ECC證書生成頁面

      UI-4

      0x05 架構設計

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

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

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

      0x06 概要設計

      通過需求分析和原型設計已經大致可以劃分出功能模塊了,核心部分就是幾個按鈕的事件監聽和處理。

      它們都可以統合到一個流程模型中:

      參數錄入->點擊按鈕->獲取參數->驗證參數->生成數據->更新UI

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

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

      異常處理:

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

      0x07 詳細設計

      將主業務流程的各個節點展開并詳細描述其實現,必要時借助偽代碼進行邏輯表示;這里就不寫了,問就是懶……

      0x08 編碼實現

      RSA根證書生成(節選關鍵部分)

      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密鑰位數" + 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(), "錯誤提示", 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 小結

      運行效果

      運行截圖-1

      運行截圖-2

      運行截圖-3

      運行截圖-4

      運行截圖-5

      運行截圖-6

      運行截圖-7

      運行截圖-8

      運行截圖-9

      完成任務。

      posted @ 2023-10-10 11:31  程語有云  閱讀(1183)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 内射囯产旡码丰满少妇| 99国产欧美久久久精品蜜芽| 色狠狠色噜噜AV一区| 国产绿帽在线视频看| 人妻少妇偷人精品一区| 正在播放国产真实哭都没用| 欧美成人精品一级在线观看| 国产av丝袜熟女一二三| 亚洲国产精久久久久久久春色| 亚洲一区久久蜜臀av| 国产不卡的一区二区三区| 人妻精品动漫H无码中字| 在线观看潮喷失禁大喷水无码| 日本三级香港三级人妇99| 国产精品一二三区视在线| 日本久久久免费高清| 116美女极品a级毛片| 国产乱色国产精品免费视频| 男女啪啪18禁无遮挡激烈| 甘洛县| 黄色特级片一区二区三区| 亚洲成av人片在www鸭子| 久久99亚洲网美利坚合众国| 国产高清国产精品国产专区| 久章草在线毛片视频播放| 特级av毛片免费观看| 女人香蕉久久毛毛片精品| 久久综合久中文字幕青草| 国产成人小视频| 日韩高清不卡免费一区二区| 日韩亚洲精品中文字幕| 国产综合久久久久鬼色| 成人性无码专区免费视频| 亚洲av免费看一区二区| 国产精品久久久一区二区三区 | 国偷自产一区二区三区在线视频| 日本一码二码三码的区分| 秋霞电影院午夜无码免费视频| 精品久久久久久亚洲综合网| 老司机亚洲精品一区二区| 亚洲精品宾馆在线精品酒店|