yeskery

Base64 编码格式的公钥证书转化为 PublicKey 类型

JAVA 做服务端,读取 pem 格式的证书和秘钥

  1. public class SocketServer extends Thread{
  2. private static final int SERVER_PORT = 10002;
  3. private SSLServerSocket serverSocket;
  4. public SocketServer() {
  5. // Initialize SSLServer
  6. try {
  7. //Load KeyStore And TrustKeyStore
  8. Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
  9. //保存服务端的私钥
  10. KeyStore keyStore = KeyStore.getInstance("JKS");
  11. keyStore.load(null, null);
  12. // // 读入服务端证书
  13. PEMReader cacertfile = new PEMReader(new InputStreamReader(
  14. new FileInputStream("d:/cacert.pem")));
  15. X509Certificate cacert = (X509Certificate) cacertfile.readObject();
  16. Certificate[] certChain = new Certificate[1];
  17. certChain[0] = cacert;
  18. cacertfile.close();
  19. // 读入私钥
  20. PEMReader kr = new PEMReader(new InputStreamReader(new FileInputStream("d:/privkey.pem")));
  21. KeyPair key = (KeyPair) kr.readObject();
  22. kr.close();
  23. // 导入服务端端私钥和证书
  24. keyStore.setKeyEntry("serverkey", key.getPrivate(), new char[]{}, certChain );
  25. keyStore.setCertificateEntry("servercert", cacert);
  26. //Initialize KeyStore Factory 创建用于管理JKS密钥库的X.509密钥管理器
  27. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
  28. keyManagerFactory.init(keyStore, "".toCharArray());
  29. //Initialize SSLContext
  30. SSLContext context = SSLContext.getInstance("TLSv1");
  31. //授权的密钥管理器,用来授权验证,
  32. context.init(keyManagerFactory.getKeyManagers(), null, null);
  33. //Set up Server Socket
  34. serverSocket = (SSLServerSocket) context.
  35. getServerSocketFactory().createServerSocket(SERVER_PORT);
  36. serverSocket.setWantClientAuth(false); //不需要客户端证书
  37. } catch (Exception e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. @Override
  42. public void run() {
  43. if(serverSocket == null){
  44. System.out.println("Null server socket");
  45. return;
  46. }
  47. try {
  48. Socket socket = serverSocket.accept();
  49. //Receive From Client
  50. InputStream input = socket.getInputStream();
  51. System.out.println("------Receive------");
  52. //use byte array to initialize the output string
  53. System.out.println(new String(StreamToByteArray(input)));
  54. if(!socket.isClosed()){
  55. //Response To Client
  56. OutputStream output = socket.getOutputStream();
  57. output.write("服务端发送123".getBytes());
  58. output.flush();
  59. socket.close();
  60. }
  61. } catch (IOException e) {
  62. e.printStackTrace();
  63. }
  64. }
  65. /**
  66. * convert stream to Byte Array
  67. * @param inputStream
  68. * @return
  69. * @throws IOException
  70. */
  71. public byte[] StreamToByteArray(InputStream inputStream) throws IOException {
  72. ByteArrayOutputStream bout = new ByteArrayOutputStream();
  73. byte[] buffer = new byte[1024];
  74. int readIndex = inputStream.read(buffer);
  75. bout.write(buffer, 0, readIndex);
  76. bout.flush();
  77. bout.close();
  78. //inputStream.close();
  79. return bout.toByteArray();
  80. }
  81. public static void main(String[] args){
  82. System.out.println("=======Start Server !======");
  83. new SocketServer().run();
  84. }
  85. }

JAVA 做客户端,读取 pem 格式的证书和秘钥

  1. public class SocketClient2 {
  2. private Logger logger = LoggerFactory.getLogger(SocketClient2.class);
  3. private String tpath = Tools.getConfig("KeyPath");// 证书路径
  4. private String ip = Tools.getConfig("ip");// 服务端ip
  5. private int port = Integer.parseInt(Tools.getConfig("port"));// 端口
  6. public static List<SSLSocket> socketList = new ArrayList<SSLSocket>();
  7. public SSLSocket getSSlSocket() {
  8. SSLContext context = null;
  9. context = this.getSSLcontext();
  10. SSLSocketFactory ssf = context.getSocketFactory();
  11. try {
  12. SSLSocket ss = (SSLSocket) ssf.createSocket("127.0.0.1", 10002);
  13. String[] protocols = { "TLSv1" }; //设置客户端协议
  14. ss.setEnabledProtocols(protocols);
  15. return ss;
  16. } catch (UnknownHostException e) {
  17. logger.error("a{}", e);
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. return null;
  22. }
  23. private SSLContext getSSLcontext() {
  24. SSLContext sslContext = null;
  25. try {
  26. // 设定Security的Provider提供程序
  27. Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
  28. // System.setProperty("https.protocols", "SSLv3,SSLv2Hello");
  29. // 建立空BKS,android只能用BKS(BouncyCastle密库),一般java应用参数传JKS(java自带密库)
  30. //访问Java密钥库,JKS是keytool创建的Java密钥库,保存密钥。
  31. KeyStore ksKeys = KeyStore.getInstance("JKS");
  32. ksKeys.load(null, null);
  33. // 读入客户端证书
  34. PEMReader cacertfile = new PEMReader(new InputStreamReader(
  35. new FileInputStream("d:/cacert.pem")));
  36. X509Certificate cacert = (X509Certificate) cacertfile.readObject();
  37. cacertfile.close();
  38. // 导入根证书作为trustedEntry
  39. //KeyStore.TrustedCertificateEntry 保存可信的 Certificate 的 KeyStore 项。
  40. KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
  41. cacert);
  42. //用指定别名保存 keystore Entry。
  43. ksKeys.setEntry("ca_root", trustedEntry, null);
  44. // 构建TrustManager 创建用于管理JKS密钥库的X.509密钥管理器。
  45. TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");// 密钥管理器
  46. tmf.init(ksKeys);
  47. // 构建SSLContext,此处传入参数为TLS,也可以为SSL
  48. sslContext = SSLContext.getInstance("TLSv1");
  49. sslContext.init(null, tmf.getTrustManagers(), null);
  50. } catch (Exception e) {
  51. e.printStackTrace();
  52. }
  53. return sslContext;
  54. }
  55. public static void main(String[] args) {
  56. SocketClient2 client = new SocketClient2();
  57. SSLSocket ss =client.getSSlSocket();
  58. try {
  59. ss.setSoTimeout(2000);
  60. OutputStream socketOut = null;
  61. if (ss != null && !ss.isClosed()) {
  62. socketOut = ss.getOutputStream();
  63. socketOut.write("客户端发送".getBytes());
  64. socketOut.flush();
  65. }
  66. if (ss != null && !ss.isClosed()) {
  67. InputStream in;
  68. in = ss.getInputStream();
  69. //input中的数据只能读取一次
  70. System.out.println(new String(StreamToByteArray(in)));
  71. }
  72. ss.close();
  73. } catch (IOException e) {
  74. // TODO Auto-generated catch block
  75. e.printStackTrace();
  76. }
  77. }
  78. /**
  79. * convert stream to Byte Array
  80. * @param inputStream
  81. * @return
  82. * @throws IOException
  83. */
  84. public static byte[] StreamToByteArray(InputStream inputStream) throws IOException {
  85. ByteArrayOutputStream bout = new ByteArrayOutputStream();
  86. byte[] buffer = new byte[1024];
  87. int readIndex = inputStream.read(buffer);
  88. bout.write(buffer, 0, readIndex);
  89. bout.flush();
  90. bout.close();
  91. return bout.toByteArray();
  92. }
  93. }

存在的问题

网上查找过相应的代码,确实给的 DEMO 是可行的,但是只是限于一定的加密算法维度,比如说 RSA4096 就不行了。

贴出相应的代码,供参考:

  1. import java.security.Key;
  2. import java.security.KeyFactory;
  3. import java.security.KeyPair;
  4. import java.security.KeyPairGenerator;
  5. import java.security.PrivateKey;
  6. import java.security.PublicKey;
  7. import java.security.Signature;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.PKCS8EncodedKeySpec;
  11. import java.security.spec.X509EncodedKeySpec;
  12. import javax.crypto.Cipher;
  13. import org.apache.commons.codec.binary.Base64;
  14. import sun.misc.BASE64Decoder;
  15. import sun.misc.BASE64Encoder;
  16. public static String str_pubK = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPvovSfXcwBbW8cKMCgwqNpsYuzF8RPAPFb7LGsnVo44JhM/xxzDyzoYtdfNmtbIuKVi9PzIsyp6rg+09gbuI6UGwBZ5DWBDBMqv5MPdOF5dCQkB2Bbr5yPfURPENypUz+pBFBg41d+BC+rwRiXELwKy7Y9caD/MtJyHydj8OUwIDAQAB";
  17. /**
  18. * 使用getPublicKey得到公钥,返回类型为PublicKey
  19. * @param base64 String to PublicKey
  20. * @throws Exception
  21. */
  22. public static PublicKey getPublicKey(String key) throws Exception {
  23. byte[] keyBytes;
  24. keyBytes = (new BASE64Decoder()).decodeBuffer(key);
  25. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  26. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  27. PublicKey publicKey = keyFactory.generatePublic(keySpec);
  28. return publicKey;
  29. }

试试这个公钥:

  1. MIIDBTCCAe2gAwIBAgIKb0XKECkuAA7bcjANBgkqhkiG9w0BAQsFADAlMRUwEwYDVQQDDAxBQkMgVEVTVCBDQTIxDDAKBgNVBAoMA0FCQzAeFw0xNzEyMjQyMTE0MDBaFw0yMjEyMjQyMTE0MDBaME4xLzAtBgNVBAMMJjQ0OTk0NDIxMzAwLjAwMDEuMDAwMC42NjQ0NTAyNTY2MjY5MzAwMQ0wCwYDVQQLDARVd2luMQwwCgYDVQQKDANBQkMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJPVlBDFMqpzYWbdGe5dkiw2uRuq6Kd9/e7TZDfwS0L3mf5/kaDs93oRSqWr497SBliQeEbA3cHphWpceUpBu7DreYvH+scSsLrR8D6t7pcVQacIqL7YDYNsCpjrmZ/DQh9Ci7AZckYVu6TzojVwbbmbjo/0C3tdfWEzSq10LM51AgMBAAGjgZEwgY4wHwYDVR0jBBgwFoAUErtyLm5Iqy6z01KtzsJ33EmoKtIwCQYDVR0TBAIwADBBBgNVHR8EOjA4MDagNKAypDAwLjEQMA4GA1UEAwwHY3JsNDQ3NDEMMAoGA1UECwwDY3JsMQwwCgYDVQQKDANBQkMwHQYDVR0OBBYEFPAOIJAri/gehQGw4RtVaqa+v2mGMA0GCSqGSIb3DQEBCwUAA4IBAQCd9ofET3kZmU0932OGIZHdqDdMhrfESmM6dTutg8SfuTnniA43qYHDZFpNa86rl4Sox0lVyIx5mhRM4edSVzfYaX0WNtYlYDqkJONcn0yRenKwjrhpnyqFM3uQsMDW0VL0+Is8PKZqiaIfjPXY2a+OqY6zGN6vpUpkM0eT2GdJLZrIKM6ufKov7cTtRDfslFBmNh6N9LWqQPsItmDyXDeUIh5IKeHn+xwaL9MjYgxYhWpkMWmRbmp0o8Vf3qKLJ0wxptjGx0dhF1CcFbv5KzJRS3DLqKJAT0N1BWI8lJDkI5B553ouPMbQmOFAMgRp0eFR++Fm0aLPlyaGBZOWzrZy

参考文章:https://www.cnblogs.com/KKatherine/p/4128444.html

在测试自己的公钥时,出现 X509.ObjectIdentifier() – data isn’t an object ID (tag = -96) error,在 https://samebug.io/exceptions/93395/java.security.InvalidKeyException/ioexception-detect-premature-eof 或许有你需要的答案,-96的错误没具体查,但是在 https://stackoverflow.com/questions/18856431/rsa-keys-transformation-for-java-clarification-needed 上的解决方法倒是提醒了我,我有了证书,为什么不直接获取公钥了?

从证书中获取

从证书文件流中获取

  1. InputStream inStream = null;
  2. try {
  3. inStream = new FileInputStream("fileName-of-cert");
  4. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  5. X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
  6. } finally {
  7. if (inStream != null) {
  8. inStream.close();
  9. }
  10. }

直接获取

  1. PublicKey myPubKey = cert.getPublicKey();

参考:https://stackoverflow.com/questions/18856431/rsa-keys-transformation-for-java-clarification-needed

本文转载自:https://blog.csdn.net/dingchenxixi/article/details/79030448

评论

发表评论 点击刷新验证码

提示

该功能暂未开放