1

我必须用数字证书建立一个网络服务,但我在这方面没有经验,我有一些例子,但对我来说还不够。在下面的代码中,我可以从 JKS 文件中获取公钥和私钥,加密字符串并验证是否分配了该字符串。但我对我应该使用谁有一些疑问:

  1. 我有 1 个私钥和 1 个公钥。如果我有多个客户调用我的网络服务,他们都需要有公钥吗?和私钥?

  2. 我应该如何将公钥发送给客户端?是文件还是字符串?我的公共测试密钥的返回是:

公钥:Sun RSA 公钥,2048 位模数:公共指数:65537

  1. 在代码中,我只能验证签名是否正确,我无法对其进行解密以获得真实值。

    导入java.io.File;导入 java.io.FileInputStream;导入 java.io.InputStream;导入 java.security.Key;导入 java.security.KeyStore;导入 java.security.PrivateKey;导入 java.security.PublicKey;导入 java.security.Signature;导入 java.security.cert.Certificate;

    公共类证书{

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
    
        String txt = "TEST_STRING";
    
        File certificado = new File("C:\\temp\\teste.jks");
        PrivateKey privateKey = getPrivateKeyFromFile(certificado, "TESTE", "123");
    
        System.out.println("PRIVATE KEY: " + privateKey.toString());
    
        PublicKey publicKey = getPublicKeyFromFile(certificado, "TESTE", "123");
    
        System.out.println("PUBLIC KEY: " + publicKey.toString());
    
        //a chave privada serve pra encriptar os dados.
        byte[] txtAssinado = createSignature( privateKey, txt.getBytes() );  
    
        System.out.println("txtAssinado: " + txt2Hexa( txtAssinado ) );
    
        if( verifySignature( publicKey, txt.getBytes(), txtAssinado ) ) {  
            System.out.println("Assinatura OK!");  
        } else {  
            System.out.println("Assinatura NOT OK!");  
        }  
    
    }
    
    public static PrivateKey getPrivateKeyFromFile( File cert, String alias, String password ) throws Exception {  
        KeyStore ks = KeyStore.getInstance ( "JKS" );  
        char[] pwd = password.toCharArray();  
        InputStream is = new FileInputStream( cert );  
        ks.load( is, pwd );  
        is.close();  
        Key key = ks.getKey( alias, pwd );  
        if( key instanceof PrivateKey ) {  
            return (PrivateKey) key;  
        }  
        return null;  
    }  
    
    /** 
     * Retorna a assinatura para o buffer de bytes, usando a chave privada. 
     * @param key PrivateKey 
     * @param buffer Array de bytes a ser assinado. 
     */  
    public static byte[] createSignature( PrivateKey key, byte[] buffer ) throws Exception {  
        Signature sig = Signature.getInstance("MD2withRSA");  
        sig.initSign(key);  
        sig.update(buffer, 0, buffer.length);  
        return sig.sign();  
    }  
    
    /** 
     * Verifica a assinatura para o buffer de bytes, usando a chave pública. 
     * @param key PublicKey 
     * @param buffer Array de bytes a ser verficado. 
     * @param sgined Array de bytes assinado (encriptado) a ser verficado. 
     */  
    public static boolean verifySignature( PublicKey key, byte[] buffer, byte[] signed ) throws Exception {  
        Signature sig = Signature.getInstance("MD2withRSA");  
        sig.initVerify(key);  
        sig.update(buffer, 0, buffer.length);  
        return sig.verify( signed );  
    }  
    
    /** 
     * Extrai a chave pública do arquivo. 
     */  
    public static PublicKey getPublicKeyFromFile( File cert, String alias, String password ) throws Exception {  
        KeyStore ks = KeyStore.getInstance ( "JKS" );  
        char[] pwd = password.toCharArray();  
        InputStream is = new FileInputStream( cert );  
        ks.load( is, pwd );  
        Key key = ks.getKey( alias, pwd );  
        Certificate c = ks.getCertificate( alias );  
        PublicKey p = c.getPublicKey();  
        return p;  
    }  
    
    public static String txt2Hexa(byte[] bytes) {  
        if( bytes == null ) return null;  
        String hexDigits = "0123456789abcdef";  
        StringBuffer sbuffer = new StringBuffer();  
        for (int i = 0; i < bytes.length; i++) {  
            int j = ((int) bytes[i]) & 0xFF;  
            sbuffer.append(hexDigits.charAt(j / 16));  
            sbuffer.append(hexDigits.charAt(j % 16));  
        }  
        return sbuffer.toString();  
    }  
    

    }

4

2 回答 2

1

你为什么需要它?如果它只是用于加密通信,您可以使用 SSL/TLS 在传输级别上执行此操作。如果是用于身份验证,我建议使用带有 WS-Policy 框架的健壮的 Web 服务堆栈(例如 Apache CXF 和 Metro)。它会为你处理低级加密货币的东西。

(当然,您可以在传输级别使用身份验证,在消息级别使用加密,但第一个将您的代码与应用程序服务器结合起来,而后者的速度非常缓慢。)

于 2012-06-27T21:07:52.153 回答
1

我决定在本教程之后使用 ws-security :

http://www.developer.com/java/other/article.php/3802631/Securing-Web-Services-in-JBoss-Application-Server-with-WS-Security.htm

谢谢!

于 2012-07-02T15:11:47.753 回答