Base64 编码格式的公钥证书转化为 PublicKey 类型
JAVA 做服务端,读取 pem 格式的证书和秘钥
public class SocketServer extends Thread{private static final int SERVER_PORT = 10002;private SSLServerSocket serverSocket;public SocketServer() {// Initialize SSLServertry {//Load KeyStore And TrustKeyStoreSecurity.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());//保存服务端的私钥KeyStore keyStore = KeyStore.getInstance("JKS");keyStore.load(null, null);// // 读入服务端证书PEMReader cacertfile = new PEMReader(new InputStreamReader(new FileInputStream("d:/cacert.pem")));X509Certificate cacert = (X509Certificate) cacertfile.readObject();Certificate[] certChain = new Certificate[1];certChain[0] = cacert;cacertfile.close();// 读入私钥PEMReader kr = new PEMReader(new InputStreamReader(new FileInputStream("d:/privkey.pem")));KeyPair key = (KeyPair) kr.readObject();kr.close();// 导入服务端端私钥和证书keyStore.setKeyEntry("serverkey", key.getPrivate(), new char[]{}, certChain );keyStore.setCertificateEntry("servercert", cacert);//Initialize KeyStore Factory 创建用于管理JKS密钥库的X.509密钥管理器KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");keyManagerFactory.init(keyStore, "".toCharArray());//Initialize SSLContextSSLContext context = SSLContext.getInstance("TLSv1");//授权的密钥管理器,用来授权验证,context.init(keyManagerFactory.getKeyManagers(), null, null);//Set up Server SocketserverSocket = (SSLServerSocket) context.getServerSocketFactory().createServerSocket(SERVER_PORT);serverSocket.setWantClientAuth(false); //不需要客户端证书} catch (Exception e) {e.printStackTrace();}}@Overridepublic void run() {if(serverSocket == null){System.out.println("Null server socket");return;}try {Socket socket = serverSocket.accept();//Receive From ClientInputStream input = socket.getInputStream();System.out.println("------Receive------");//use byte array to initialize the output stringSystem.out.println(new String(StreamToByteArray(input)));if(!socket.isClosed()){//Response To ClientOutputStream output = socket.getOutputStream();output.write("服务端发送123".getBytes());output.flush();socket.close();}} catch (IOException e) {e.printStackTrace();}}/*** convert stream to Byte Array* @param inputStream* @return* @throws IOException*/public byte[] StreamToByteArray(InputStream inputStream) throws IOException {ByteArrayOutputStream bout = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int readIndex = inputStream.read(buffer);bout.write(buffer, 0, readIndex);bout.flush();bout.close();//inputStream.close();return bout.toByteArray();}public static void main(String[] args){System.out.println("=======Start Server !======");new SocketServer().run();}}
JAVA 做客户端,读取 pem 格式的证书和秘钥
public class SocketClient2 {private Logger logger = LoggerFactory.getLogger(SocketClient2.class);private String tpath = Tools.getConfig("KeyPath");// 证书路径private String ip = Tools.getConfig("ip");// 服务端ipprivate int port = Integer.parseInt(Tools.getConfig("port"));// 端口public static List<SSLSocket> socketList = new ArrayList<SSLSocket>();public SSLSocket getSSlSocket() {SSLContext context = null;context = this.getSSLcontext();SSLSocketFactory ssf = context.getSocketFactory();try {SSLSocket ss = (SSLSocket) ssf.createSocket("127.0.0.1", 10002);String[] protocols = { "TLSv1" }; //设置客户端协议ss.setEnabledProtocols(protocols);return ss;} catch (UnknownHostException e) {logger.error("a{}", e);} catch (IOException e) {e.printStackTrace();}return null;}private SSLContext getSSLcontext() {SSLContext sslContext = null;try {// 设定Security的Provider提供程序Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());// System.setProperty("https.protocols", "SSLv3,SSLv2Hello");// 建立空BKS,android只能用BKS(BouncyCastle密库),一般java应用参数传JKS(java自带密库)//访问Java密钥库,JKS是keytool创建的Java密钥库,保存密钥。KeyStore ksKeys = KeyStore.getInstance("JKS");ksKeys.load(null, null);// 读入客户端证书PEMReader cacertfile = new PEMReader(new InputStreamReader(new FileInputStream("d:/cacert.pem")));X509Certificate cacert = (X509Certificate) cacertfile.readObject();cacertfile.close();// 导入根证书作为trustedEntry//KeyStore.TrustedCertificateEntry 保存可信的 Certificate 的 KeyStore 项。KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(cacert);//用指定别名保存 keystore Entry。ksKeys.setEntry("ca_root", trustedEntry, null);// 构建TrustManager 创建用于管理JKS密钥库的X.509密钥管理器。TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");// 密钥管理器tmf.init(ksKeys);// 构建SSLContext,此处传入参数为TLS,也可以为SSLsslContext = SSLContext.getInstance("TLSv1");sslContext.init(null, tmf.getTrustManagers(), null);} catch (Exception e) {e.printStackTrace();}return sslContext;}public static void main(String[] args) {SocketClient2 client = new SocketClient2();SSLSocket ss =client.getSSlSocket();try {ss.setSoTimeout(2000);OutputStream socketOut = null;if (ss != null && !ss.isClosed()) {socketOut = ss.getOutputStream();socketOut.write("客户端发送".getBytes());socketOut.flush();}if (ss != null && !ss.isClosed()) {InputStream in;in = ss.getInputStream();//input中的数据只能读取一次System.out.println(new String(StreamToByteArray(in)));}ss.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** convert stream to Byte Array* @param inputStream* @return* @throws IOException*/public static byte[] StreamToByteArray(InputStream inputStream) throws IOException {ByteArrayOutputStream bout = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int readIndex = inputStream.read(buffer);bout.write(buffer, 0, readIndex);bout.flush();bout.close();return bout.toByteArray();}}
存在的问题
网上查找过相应的代码,确实给的 DEMO 是可行的,但是只是限于一定的加密算法维度,比如说 RSA4096 就不行了。
贴出相应的代码,供参考:
import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.PrivateKey;import java.security.PublicKey;import java.security.Signature;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;import org.apache.commons.codec.binary.Base64;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public static String str_pubK = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPvovSfXcwBbW8cKMCgwqNpsYuzF8RPAPFb7LGsnVo44JhM/xxzDyzoYtdfNmtbIuKVi9PzIsyp6rg+09gbuI6UGwBZ5DWBDBMqv5MPdOF5dCQkB2Bbr5yPfURPENypUz+pBFBg41d+BC+rwRiXELwKy7Y9caD/MtJyHydj8OUwIDAQAB";/*** 使用getPublicKey得到公钥,返回类型为PublicKey* @param base64 String to PublicKey* @throws Exception*/public static PublicKey getPublicKey(String key) throws Exception {byte[] keyBytes;keyBytes = (new BASE64Decoder()).decodeBuffer(key);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(keySpec);return publicKey;}
试试这个公钥:
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 上的解决方法倒是提醒了我,我有了证书,为什么不直接获取公钥了?
从证书中获取
从证书文件流中获取
InputStream inStream = null;try {inStream = new FileInputStream("fileName-of-cert");CertificateFactory cf = CertificateFactory.getInstance("X.509");X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);} finally {if (inStream != null) {inStream.close();}}
直接获取
PublicKey myPubKey = cert.getPublicKey();
参考:https://stackoverflow.com/questions/18856431/rsa-keys-transformation-for-java-clarification-needed
本文转载自:https://blog.csdn.net/dingchenxixi/article/details/79030448
评论