1

デジタル証明書を使用して Web サービスを構築する必要がありますが、この分野での経験がありません。いくつかの例を入手しましたが、まだ十分ではありませんでした。以下のコードでは、JKS ファイルから公開鍵と秘密鍵を取得し、文字列を暗号化し、その文字列が割り当てられているかどうかを確認できます。しかし、私はそれを誰に使うべきかについていくつか疑問があります:

  1. 私は 1 つの秘密鍵と 1 つの公開鍵を持っています。複数のクライアントが Web サービスを呼び出している場合、両方のクライアントが公開鍵を持っている必要がありますか? そして秘密鍵?

  2. 公開鍵をクライアントに送信するにはどうすればよいですか? ファイルまたは文字列ですか? 私の公開テストキーの戻り値は次のとおりです。

PUBLIC KEY: 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 をインポートします。

    public class 証明書 {

    /**
     * @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

このチュートリアルに従って、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 に答える
1

なぜあなたはそれが必要なのですか?暗号化された通信だけの場合は、SSL/TLS を使用してトランスポート レベルでそれを行うことができます。認証用の場合は、WS-Policy フレームワークを使用した堅牢な Web サービス スタック (Apache CXF や Metro など) をお勧めします。低レベルの暗号化を処理します。

(もちろん、トランスポート レベルで認証を使用し、メッセージ レベルで暗号化を使用できますが、前者はコードをアプリケーション サーバーと結合し、後者は非常に遅くなります。)

于 2012-06-27T21:07:52.153 に答える