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

时间:2012-06-27 21:03:53

标签: java web-services security digital-signature

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

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

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

  3. PUBLIC KEY:Sun RSA公钥,2048位   模量:17250324892612486858507429685448839704055777462217619737452934774822672851497966978790916432466790842915878683120882004958695145419939098968836614824888409393052061936762455389263916348884908835001481590512979961376093665985176086582620326688971144157926968064917610077028818131909416605240046026228844714588221891425654992455455846135152245033503553286312978619541722235228388013887009488301495951905133704760137236960349458111717499961995019021977295294912070129505927611114331851407796798585518424426757876237265884912360355209124912153937505471115177310252984915833469781596755813935167181407292034238159965045653   公共指数:65537

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

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

      公共类Certificado {

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

      }

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)