java - 如何使用数字证书创建Web服务

标签 java web-services security digital-signature

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

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

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

公钥:Sun RSA 公钥,2048 位 模数: 1725032489261248685850742968544883970405577746221761973745293477482267285149796697879091643246679084291587868312088200 495869514541993909896883661482488840939305206193676245538926391634888490883500148159051297996137609366598517608658262032668 897114415792696806491761007702881813190941660524004602622884471458822189142565499245545584613515224503350355328631297861954 172223522838801388700948830149595190513370476013723696034945811171749996199501902197729529491207012950592761111433185140779 679858551842442675787623726588491236035520912491215393750547111517731025298491583346978159675581393516718140729203423815996 5045653 公共(public)指数: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;

    公共(public)类证书{

    /**
     * @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();  
    }  
    

    }

最佳答案

为什么需要它?如果只是为了加密通信,您可以使用 SSL/TLS 在传输级别上实现这一点。如果是为了身份验证,我建议使用带有 WS-Policy 框架的强大的 Web 服务堆栈(例如 Apache CXF 和 Metro)。它会为您处理低级加密内容。

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

关于java - 如何使用数字证书创建Web服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11234776/

相关文章:

java - 如何在 Java 中指定文件的路径?

Java - 仅比较特定键的两个 Maps 条目

java - 使用 Apache CXF 的 JAXWS Web 服务 - 名称 ""对于 JDOM/XML 命名空间 : Namespace URIs must be non-null and non-empty Strings 是不合法的

c# - 分割用户名和密码凭证

web-services - 为什么我要使用 WCF 以外的任何东西?

rest - 为什么 google-oauth API 需要重定向 URL?

.net - 从网络共享运行 "partially trusted".NET 程序集

php - 这个php代码安全吗?

java - 在 Java 中重新绘制 BufferedImage 不会更改面板的内容

java - 将 pcm 转换为 .wav - 有噪音