我試圖讓我的應用程序通過https與我的服務器通信。 因爲我不想支付讓我的服務器證書由受信任的CA簽名,所以解決方案是使用自簽名證書。沒有對等證書異常 - 排除和Android自簽名證書
所以,我已經建立了我caconfig.cnf如下:
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = ./demoCA # top dir
database = $dir/index.txt # index file.
new_certs_dir = $dir/newcerts # new certs dir
certificate = $dir/cacert.pem # The CA cert
serial = $dir/serial # serial no file
private_key = $dir/private/cakey.pem # CA private key
RANDFILE = $dir/private/.rand # random number file
default_days = 365 # how long to certify for
default_crl_days = 30 # how long before next CRL
default_md = md5 # md to use
policy = policy_any # default policy
email_in_dn = no # Don't add the email into cert DN
name_opt = ca_default # Subject name display option
cert_opt = ca_default # Certificate display option
copy_extensions = none # Don't copy extensions from request
[ policy_any ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
然後,我創建並使用以下命令簽署我的證書:
$ mkdir myCA myCA/private myCA/newcerts
$ echo "01" > myCA/serial
$ touch demoCA/index.txt
$ openssl genrsa -des3 -out myCA/private/cakey.pem 1024
$ openssl req -new -x509 -days 3650 -key myCA/private/cakey.pem -out myCA/cacert.pem
$ openssl req -sha1 -newkey rsa:2048 -keyout server-key.pem -out server-cert-req.pem -subj '/CN=myhost/' -nodes
$ openssl ca -config caconfig.cnf -in server-cert-req.pem -out server-cert.pem
$ openssl x509 -inform PEM -in cacert.pem -outform DER -out certificate.cer
$ rm server-cert-req.pem
在我的服務器的NodeJS代碼,我創建這樣的https服務器:
var express = require('express');
var https = require('https');
var PORT = 443;
var app = express();
app.get('/', function (req, res) {
res.send("Server is working");
});
var httpsOptions = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
https.createServer(httpsOptions, app).listen(PORT, function() {
console.log('%s: Node server started on port %d ...', Date(Date.now()), PORT);
});
爲了測試一切是否正確,我還創建了一個節點客戶端腳本,向我的服務器發出請求。下面是我的節點客戶端代碼:
var https = require('https');
var fs = require('fs');
var request = https.request({
host: 'myhost',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: true,
// Once it is self signed, I'm using my server certificate (public key).
ca: [fs.readFileSync('cacert.pem').toString()]
}, function(response) {
response.on('data', function(data) {
console.log(data.toString());
});
});
request.on('error', function(err) {
console.log(err);
})
request.end();
當我運行我的節點客戶端腳本時,它完美地工作。另一方面,我用來檢查Volley如何與https協同工作的Android Volley Examples應用程序無法正常工作。下面,我正在描述爲了使其工作而遵循的所有步驟。
我已經用我的certificate.cer文件中使用以下命令創建一個.bks文件:
keytool -importcert -v -trustcacerts -file "certificate.cer" -alias IntermediateCA -keystore "res/raw/my_keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret
然後,我如果證書正確導入.bks如下驗證:
keytool -list -keystore "res/raw/my_keystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-146.jar" -storetype BKS -storepass mysecret
而且我得到了下面的輸出,這意味着它是正確的:
Keystore type: BKS
Keystore provider: BC
Your keystore contains 1 entry
imeto_alias, Oct 16, 2014, trustedCertEntry,
Certificate fingerprint (SHA1): 03:DC:A1:6A:9B:1D:AD:59:A9:9B:1F:C2:43:7E:80:07:3B:B6:BE:CB
我來了對這個tutorial,並且,因爲我使用了Volley,我決定遵循它。所以,下面是我對示例項目做出的以下更改。
Got Volley from git clone https://android.googlesource.com/platform/frameworks/volley
Got Android Volley Examples project from git clone git://github.com/ogrebgr/android_volley_examples.git
Copied my_keystore.bks containing the self-signed public key in res/raw;
Opened Act_SsSslHttpClient in the examples project, found "R.raw.test" and replaced it with R.raw.my_keystore;
Found "new SslHttpClient(" and replaced the default password "test123″ with "mysecret";
Replaced "44400" with the HTTPS port of my server/virtualhost ("443"). (I could also remove this parameter since "443" is the default port;
Replaced "https://tp.bolyartech.com:44400/https_test.html" with my server URL.
Started the app, went to "HTTPS with self-signed cert", then "Execute HTTPS request"
但是,當我按下按鈕,我得到了以下異常:
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
下面,是我JavaCode ...
public class Act_SsSslHttpClient extends Activity {
private TextView mTvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act__ss_ssl_http_client);
mTvResult = (TextView) findViewById(R.id.tv_result);
Button btnSimpleRequest = (Button) findViewById(R.id.btn_simple_request);
btnSimpleRequest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Replace R.raw.test with your keystore
InputStream keyStore = getResources().openRawResource(R.raw.my_keystore);
// Usually getting the request queue shall be in singleton like in {@seeAct_SimpleRequest}
// Current approach is used just for brevity
RequestQueue queue = Volley.newRequestQueue(Act_SsSslHttpClient.this,
new ExtHttpClientStack(new SslHttpClient(keyStore,
"mysecret")));
StringRequest myReq = new StringRequest(Method.GET,
"https://myServerURL/",
createMyReqSuccessListener(),
createMyReqErrorListener());
queue.add(myReq);
}
});
}
...
}
有誰知道解決的辦法? 謝謝。
我們無法真正幫助您在不看到Java代碼的情況下調試Java代碼。 – CommonsWare 2014-10-16 19:58:53
@CommonsWare,我對我的問題做了一些修改。你現在可以幫我嗎?謝謝... – arthursfreire 2014-10-16 21:25:16
我不能,因爲我不使用Volley。但沒有代碼,沒有人能夠幫助你。現在,如果有一個使用定製SSL的Volley專家,他們可能會根據他們看到的內容提供一些建議。 – CommonsWare 2014-10-16 21:29:14