Próbuję sprawić, aby moja aplikacja komunikowała się z moim serwerem za pośrednictwem https. Ponieważ nie chcę płacić za podpisanie mojego certyfikatu serwera przez zaufany urząd certyfikacji, rozwiązaniem jest użycie certyfikatu z podpisem własnym.Brak certyfikatu równorzędnego Wyjątek - Volley i Android z samopodpisanym certyfikatem
Więc stworzyłem mój caconfig.cnf następująco:
[ 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
Potem stworzyliśmy i podpisał mój certyfikat za pomocą następujących poleceń:
$ 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
W moim serwerze nodejs Kod, tworzę serwer https w ten sposób:
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);
});
Aby sprawdzić, czy wszystko jest poprawne, Stworzyłem również skrypt klienta węzła, który wysyła żądanie do mojego serwera. Oto kod dla mojego klienta węzła:
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();
Po uruchomieniu skryptu klienta węzła działa on idealnie. Z drugiej strony, aplikacja Android Volley Examples, której używam do sprawdzania, jak Volley współpracuje z https, nie działa. Poniżej opisuję wszystkie kroki, które podjąłem, aby spróbować działać.
Utworzyłem bks plik za pomocą mój plik certificate.cer za pomocą następującego polecenia:
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
Potem zweryfikowaniu, czy certyfikat został poprawnie importowane do .bks następująco:
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
I mam następujący wynik, to znaczy, że jest poprawne:
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
ja przyszedł do tego tutorial, i jak używam Volley, zdecydowałem się na to. Poniżej znajdują się następujące zmiany, które wprowadziłem do przykładowego projektu.
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"
Ale kiedy wciśnięty przycisk, mam następujący wyjątek:
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Poniżej jest mój 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);
}
});
}
...
}
Czy ktoś zna rozwiązanie? Dziękuję.
Naprawdę nie możemy pomóc w debugowaniu kodu Java bez zobaczenia kodu Java. – CommonsWare
@CommonsWare, wprowadziłem pewne zmiany w moim pytaniu. Czy możesz mi teraz pomóc? Dzięki ... – arthursfreire
Nie mogę, bo nie używam Volley. Ale bez kodu nikt nie byłby w stanie ci pomóc. Teraz, jeśli istnieje specjalistyczny ekspert Volley używający SSL, mogą oni mieć pewne sugestie na podstawie tego, co widzą. – CommonsWare