Https Jsse java Ssl 研究2

1、如果想要在ssl通信中,明確使用某個Key(非對稱密鑰),那麼我們需要自己手動實現X509KeyManager接口。在SSLContext的init方法中,第一個參數是keymanager數組(必須是X509KeyManager格式),這個數組中的第一個keyManager就是通信使用的key,其他的都會忽略。如果沒有X509KeyManager格式的keyManager,那麼不會拋出異常,只是不能正常工作。

 

   實現我們自己的X509KeyManager,必須實現

public String[] getClientAliases(String keyType, Principal[] issuers)

Return all possible aliases (from the keystore) that could be used to perform client−side SSL
encryption for the given key type (e.g., RSA or DSA). If the issuers array is not null, it will
contain an array of principals who are CAs. The key belonging to an alias in the returned array must
have been issued by an entity contained in the array.
This method should not return null; if no appropriate aliases are found, it should return an array of
length 0.

返回該keystore裏所有合適的別名,根據指定的密鑰類型能夠執行客戶端ssl加密。如果issuers數組不是空,那麼返回的數組中的數據必須是某個實體頒發的。

 

public String chooseClientAlias(String keyType, Principal[] issuers)
Select the alias (from the keystore) that should be used to perform client−side SSL encryption for the
given key type (e.g., RSA or DSA). If the issuers array is not null, the key must be provided by
an entity contained in the array. This method should return null if no appropriate alias is found.

根據密鑰類型和頒發者,返回一個客戶端可以使用的密鑰別名

public String[] getServerAliases(String keyType, Principal[] issuers)
Return all possible aliases (from the keystore) that could be used to perform server−side SSL
encryption for the given key type (e.g., RSA or DSA). If the issuers array is not null, the key
must be provided by an entity contained in the array.
This method should not return null; if no appropriate aliases are found, it should return an array of
length 0.

返回所有的服務端可以執行ssl加密的密鑰別名數組,根據知道的密鑰類型和頒發類型

public String chooseServerAlias(String keyType, Principal[] issuers)
Select the alias (from the keystore) that should be used to perform server−side SSL encryption for the
given key type (e.g., RSA or DSA). If the issuers array is not null, the key must be provided by
an entity contained in the array. This method should return null if no appropriate alias is found.

選擇一個服務器執行ssl加密的密鑰別名

 

public X509Certificate[] getCertificateChain(String alias)
Return the array of X509 certificates associated with the given alias. If the keystore contains
non−X509 certificates for the given alias, those certificates should be ignored. Note that the method
returns an array of java.security.cert.X509Certificate objects, not (as do most other
classes within JSSE) javax.security.cert.X509Certificate objects.

返回指定別名的X509格式的證書數組

 

As the API indicates, key managers may be used by both clients and servers in an SSL conversation. They are
more frequently used by servers, since servers must always authenticate themselves to clients.

一般用於客戶端和服務端的ssl會話期間,但是在服務端最頻繁使用,因爲一般情況客戶端需要驗證服務器

 

一下是一個實現X509KeyManager的實例

public class SSLKeyManager implements X509KeyManager {
protected String alias;
protected KeyStore ks;
protected char[] pw;

private String type;
private String issuer;
SSLKeyManager(KeyStore ks, String s, char[] pw) {
this.ks = ks;
alias = s;
this.pw = pw;
try {
java.security.cert.Certificate c = ks.getCertificate(s);
type = c.getPublicKey().getAlgorithm( );
issuer = ((X509Certificate) c).getIssuerDN().getName( );
} catch (Exception e) {
throw new IllegalArgumentException(s + " has a bad key");
}
}

 

public String chooseClientAlias(String type, Principal[] issuers) {
if (!type.equals(this.type))
return null;
if (issuers == null)
return alias;
for (int i = 0; i < issuers.length; i++) {
if (issuer.equals(issuers[i].getName( )))
return alias;
}
return null;
}

 

public String chooseServerAlias(String type, Principal[] issuers) {
return chooseClientAlias(type, issuers);
}

 

// Get the certificates −− make sure each is an X509Certificate
// before copying it into the array.
public X509Certificate[] getCertificateChain(String s) {
try {
java.security.cert.Certificate[] c =
ks.getCertificateChain(s);
Vector c2 = new Vector(c.length);
for (int i = 0; i < c.length; i++)
c2.add(c[i]);
return (X509Certificate[])
c2.toArray(new X509Certificate[0]);
} catch (KeyStoreException kse) {
return null;
}
}

public String[] getClientAliases(String type, Principal[] p) {
String[] s;
String alias = chooseClientAlias(type, p);
if (alias == null)
s = new String[0];
else {
s = new String[1];
s[0] = alias;
}
return s;
}

public String[] getServerAliases(String type, Principal[] p) {
return getClientAliases(type, p);
}

public PrivateKey getPrivateKey(String alias) {
try {
return (PrivateKey) ks.getKey(alias, pw);
} catch (Exception e) {
return null;
}
}
}

Since we've specified an alias we treat client and server authorization the same way, though you could extend
this idea to provide different aliases or otherwise treat the server authentication differently.

我們可以使用不同的別名在服務器和客戶端

 

As a result of this simplification, most methods end up calling the choose−ClientAlias( ) method.
This method checks to see if the key algorithm type matches and, if appropriate, if the key was provided by an
entry in the issuers array. If everything matches, it returns the alias we want; otherwise it returns null.

 

2、實現KeyManagerFactorySpi引擎,

必須實現protected abstract void engineInit(KeyStore keystore,char[] password);
和protected abstract KeyManager[] engineGetKeyManager();
 
public class SSLKeyManagerFactory extends KeyManagerFactorySpi{
     char[] pw;KeyStore ks;String alias;
public SSLKeyManagerFactory( ) {
alias = System.getProperty("xyz.aliasName");
if (alias == null)
throw new IllegalArgumentException(
"Must specify alias property");
}
protected KeyManager[] engineGetKeyManagers( ) {
SSLKeyManager[] km = new SSLKeyManager[1];
km[0] = new SSLKeyManager(ks, alias, pw);
return km;}
}
protected void engineInit(KeyStore ks, char[] pw) {
this.ks = ks;
this.pw = new char[pw.length];
System.arraycopy(pw, 0, this.pw, 0, pw.length);
}
}
 
This engine class requires a security provider, of course; we'll use the provider from Chapter 8, which
contains this mapping:
put("KeyManagerFactory.XYZ",
"javasec.samples.ch14.SSLKeyManagerFactory");
Finally, here's how we use the key manager within our server:
package javasec.samples.ch14;
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.*;
import javax.net.ssl.*;
import javax.security.cert.*;
import com.sun.net.ssl.*;
import javasec.sample.ch08.XYZProvider;
public class SSLServerKeyManager {
public static void main(String[] args) throws Exception {
Security.addProvider(new XYZProvider( ));
SSLContext sc = SSLContext.getInstance("TLS");
KeyStore ks = KeyStore.getInstance("jceks");
char[] password = args[1].toCharArray( );
ks.load(new FileInputStream(args[0]), null);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("XYZ");
kmf.init(ks, password);
sc.init(kmf.getKeyManagers( ), null, null);
ServerSocketFactory ssf = sc.getServerSocketFactory( );
ServerSocket ss = ssf.createServerSocket(9096);
while (true) {
new SSLSimpleServer(ss.accept()).start( );
}
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章