【问题标题】:java.io.IOException: Wrong version of key store. using SpongyCastlejava.io.IOException:密钥库的版本错误。使用海绵城堡
【发布时间】:2014-06-22 20:25:24
【问题描述】:

我正在使用 Spongycastle 并希望以编程方式创建自签名证书。当我在 Android 中运行以下代码时,我得到 java.io.IOException: Wrong version of key store.

我不确定我做错了什么,我认为 Spongycastle 是正确的版本?

这里是代码:

import org.spongycastle.jce.X509Principal;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.x509.X509V3CertificateGenerator;

import javax.net.ssl.*;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Date;

public class HttpsHello {
    private static String domainName = "localhost";
    static { Security.addProvider(new BouncyCastleProvider());  }

    public static void test() {

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            KeyPair KPair = keyPairGenerator.generateKeyPair();

            X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();

             int ran = new SecureRandom().nextInt();
            if (ran < 0) ran = ran *-1;

            BigInteger serialNumber = BigInteger.valueOf(ran);

            v3CertGen.setSerialNumber(serialNumber);
            v3CertGen.setIssuerDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));
            v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30));
            v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365*10)));
            v3CertGen.setSubjectDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));


            v3CertGen.setPublicKey(KPair.getPublic());
            v3CertGen.setSignatureAlgorithm("MD5WithRSAEncryption");

            X509Certificate pkcert = v3CertGen.generateX509Certificate(KPair.getPrivate());
        //    FileOutputStream fos = new FileOutputStream("/path/to/testCert.cert");
          //  fos.write(pkcert.getEncoded());
           // fos.close();

            ByteArrayInputStream cert = new ByteArrayInputStream(pkcert.getEncoded());

            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

            ks.load(cert,null);
            KeyManagerFactory kmf =
                    KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, null);
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(kmf.getKeyManagers(), null, null);
            SSLServerSocketFactory ssf = sc.getServerSocketFactory();
            SSLServerSocket s
                    = (SSLServerSocket) ssf.createServerSocket(8888);
            System.out.println("Server started:");
            printServerSocketInfo(s);
            // Listening to the port
            SSLSocket c = (SSLSocket) s.accept();
            printSocketInfo(c);
            BufferedWriter w = new BufferedWriter(
                    new OutputStreamWriter(c.getOutputStream()));
            BufferedReader r = new BufferedReader(
                    new InputStreamReader(c.getInputStream()));
            String m = r.readLine();
            w.write("HTTP/1.0 200 OK");
            w.newLine();
            w.write("Content-Type: text/html");
            w.newLine();
            w.newLine();
            w.write("<html><body>Hello world!</body></html>");
            w.newLine();
            w.flush();
            w.close();
            r.close();
            c.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: "+s.getClass());
        System.out.println("   Remote address = "
                +s.getInetAddress().toString());
        System.out.println("   Remote port = "+s.getPort());
        System.out.println("   Local socket address = "
                +s.getLocalSocketAddress().toString());
        System.out.println("   Local address = "
                +s.getLocalAddress().toString());
        System.out.println("   Local port = "+s.getLocalPort());
        System.out.println("   Need client authentication = "
                +s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("   Cipher suite = "+ss.getCipherSuite());
        System.out.println("   Protocol = "+ss.getProtocol());
    }
    private static void printServerSocketInfo(SSLServerSocket s) {
        System.out.println("Server socket class: "+s.getClass());
        System.out.println("   Socker address = "
                +s.getInetAddress().toString());
        System.out.println("   Socker port = "
                +s.getLocalPort());
        System.out.println("   Need client authentication = "
                +s.getNeedClientAuth());
        System.out.println("   Want client authentication = "
                +s.getWantClientAuth());
        System.out.println("   Use client mode = "
                +s.getUseClientMode());
    }
}

【问题讨论】:

    标签: java android bouncycastle spongycastle


    【解决方案1】:

    我认为它在下面一行:

    ks.load(cert,null);
    

    'load' 用于加载 KeyStore 文件。您正在尝试加载证书。这两者的格式完全不同,这就是您收到错误的原因。

    【讨论】:

    • 好点,谢谢。现在我收到了java.security.NoSuchAlgorithmException: KeyManagerFactory SunX509 implementation not found,我想我得开始研究这个错误了。我什至需要加载密钥库方法吗?我应该做一个密钥库吗?
    • 支持的算法取决于加密提供者,但这里描述了最常见的算法:docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/…(查找加密算法)。通常人们使用存储在文件中的 KeyStore,但是在您想要动态创建证书的情况下,您需要找到一种动态创建 KeyStore 对象并在那里加载密钥的方法,或者创建一个临时密钥库文件,导入您的证书在那里,然后使用该密钥库文件。
    • 我想,我刚刚找到了一个可能适合您的解决方案。看起来您可以使用 ks.load(null),然后使用 ks.setSertifcateEntry。在此处查看详细信息:stackoverflow.com/questions/18513792/…
    • 谢谢,我试试看。
    猜你喜欢
    • 2012-01-13
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 2022-12-14
    • 2013-05-25
    • 2012-06-22
    相关资源
    最近更新 更多