Android SSL 私簽憑證連線(使用自簽名的SSL / TLS )
發表人:
Seachaos
積分: 2432
積分: 2432
有些時候基於安全性但又不想買 SSL/TLS 憑證
這時就可以用自簽的憑證 (self signed certificate ) 來讓Android建立安全連線
以下使用Google的網址來做範例,
先使用FireFox來建立一個私有的憑證(DER)
1. 在網址列點一下鎖頭,然後按更多資訊
2. 移到「安全」頁面,然後按下「檢視憑證」
3.再按「詳細資訊」,然後按下「匯出」
4.然後將他命名成cert.crt,放置到Android的assets下,讓我們的程式可以去讀取到這個憑證檔
格式記得選X.509 憑證 ( DER )
以下是http connect class範列:
[sea:javaCode]
import android.content.Context;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
/**
* Created by seachaos on 11/8/15.
*/
public class SSLSelfSender {
KeyStore trustStore = null;
public String send(Context context, String urlString){
//建立 ssl context
SSLContext sslContext = prepareSelfSign(context);
if(trustStore==null||sslContext==null){
return null;
}
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = null;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
e.printStackTrace();
}
if(url==null){
return null;
}
try {
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
// 使用ssl context
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
// 讀取結果
InputStream is = urlConnection.getInputStream();
if (is != null) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte data[] = new byte[256];
int length = 0, getPer = 0;
while ((getPer = is.read(data)) != -1) {
length += getPer;
byteArrayOutputStream.write(data, 0, getPer);
}
is.close();
byteArrayOutputStream.close();
String utf8 = new String(byteArrayOutputStream.toByteArray(), "UTF-8").trim();
return utf8;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public SSLContext prepareSelfSign(Context context){
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
} catch (KeyStoreException e) {
e.printStackTrace();
}
if(trustStore==null){
return null;
}
SSLContext sslContext = null;
InputStream crtInput = null;
try {
// 載入憑證檔
crtInput = context.getAssets().open("cert.crt");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(crtInput);
Certificate ca = cf.generateCertificate(caInput);
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(trustStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} finally {
if(crtInput!=null) {
try {
crtInput.close();
} catch (IOException e) {
}
}
}
return sslContext;
}
}
[/sea]
使用此Class的範例:
[sea:javaCode]
public void sslTest(){
SSLSelfSender https = new SSLSelfSender();
String resp = https.send(this, "https://www.google.com.tw");
debug("resp:" + resp);
}
[/sea]
以上是用google的來做測試,所以這個寫法如果去連接其他的網站就會得到錯誤
但適合用在自簽的ssl憑證上
這時就可以用自簽的憑證 (self signed certificate ) 來讓Android建立安全連線
以下使用Google的網址來做範例,
先使用FireFox來建立一個私有的憑證(DER)
1. 在網址列點一下鎖頭,然後按更多資訊
2. 移到「安全」頁面,然後按下「檢視憑證」
3.再按「詳細資訊」,然後按下「匯出」
4.然後將他命名成cert.crt,放置到Android的assets下,讓我們的程式可以去讀取到這個憑證檔
格式記得選X.509 憑證 ( DER )
以下是http connect class範列:
[sea:javaCode]
import android.content.Context;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
/**
* Created by seachaos on 11/8/15.
*/
public class SSLSelfSender {
KeyStore trustStore = null;
public String send(Context context, String urlString){
//建立 ssl context
SSLContext sslContext = prepareSelfSign(context);
if(trustStore==null||sslContext==null){
return null;
}
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = null;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
e.printStackTrace();
}
if(url==null){
return null;
}
try {
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
// 使用ssl context
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
// 讀取結果
InputStream is = urlConnection.getInputStream();
if (is != null) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte data[] = new byte[256];
int length = 0, getPer = 0;
while ((getPer = is.read(data)) != -1) {
length += getPer;
byteArrayOutputStream.write(data, 0, getPer);
}
is.close();
byteArrayOutputStream.close();
String utf8 = new String(byteArrayOutputStream.toByteArray(), "UTF-8").trim();
return utf8;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public SSLContext prepareSelfSign(Context context){
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
} catch (KeyStoreException e) {
e.printStackTrace();
}
if(trustStore==null){
return null;
}
SSLContext sslContext = null;
InputStream crtInput = null;
try {
// 載入憑證檔
crtInput = context.getAssets().open("cert.crt");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(crtInput);
Certificate ca = cf.generateCertificate(caInput);
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(trustStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} finally {
if(crtInput!=null) {
try {
crtInput.close();
} catch (IOException e) {
}
}
}
return sslContext;
}
}
[/sea]
使用此Class的範例:
[sea:javaCode]
public void sslTest(){
SSLSelfSender https = new SSLSelfSender();
String resp = https.send(this, "https://www.google.com.tw");
debug("resp:" + resp);
}
[/sea]
以上是用google的來做測試,所以這個寫法如果去連接其他的網站就會得到錯誤
但適合用在自簽的ssl憑證上