我必须建立一个带有数字证书的网络服务,但我没有这方面的经验,我有一些例子,但对我来说还不够。在下面的代码中,我可以从JKS文件获取公钥和私钥,加密字符串并验证是否分配了该字符串。但我怀疑我应该使用它:
我有1个私钥和1个公钥。如果我有多个客户呼叫我的网络服务,他们都需要公钥?和私钥?
我应该如何将公钥发送给客户?是文件还是字符串?我的公共测试密钥的返回是:
PUBLIC KEY:Sun RSA公钥,2048位 模量:17250324892612486858507429685448839704055777462217619737452934774822672851497966978790916432466790842915878683120882004958695145419939098968836614824888409393052061936762455389263916348884908835001481590512979961376093665985176086582620326688971144157926968064917610077028818131909416605240046026228844714588221891425654992455455846135152245033503553286312978619541722235228388013887009488301495951905133704760137236960349458111717499961995019021977295294912070129505927611114331851407796798585518424426757876237265884912360355209124912153937505471115177310252984915833469781596755813935167181407292034238159965045653 公共指数:65537
在代码中,我只能验证签名是否正确,我无法解密,以获得真正的价值。
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();
}
}
答案 0 :(得分:1)
你为什么需要它?如果它只是用于加密通信,您可以使用SSL / TLS在传输级别上执行此操作。如果是用于身份验证,我会建议使用WS-Policy框架的健壮的Web服务堆栈(例如Apache CXF和Metro)。它会照顾你的低级加密内容。
(您可以在传输级别使用身份验证,在消息级别使用加密,但第一次将您的代码与应用程序服务器联系起来,后者的速度非常慢。)
答案 1 :(得分:1)