/*
* Copyright 2013 mpowers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.trsst;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyManagementException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.abdera.Abdera;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Element;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.lang3.StringEscapeUtils;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.util.encoders.Hex;
import org.w3c.tidy.Tidy;
import com.trsst.client.AnonymSSLSocketFactory;
/**
* Shared utilities and constants used by both clients and servers. Portions
* borrowed from bitsofproof, abdera, and apache commons.
*
* @author mpowers
*/
public class Common {
public static final String ROOT_ALIAS = "home";
public static final String ACCOUNT_PREFIX = "acct:";
public static final String ACCOUNT_URN_PREFIX = "urn:acct:";
public static final String ACCOUNT_URN_FEED_PREFIX = ":feed:";
public static final String FEED_URN_PREFIX = "urn:feed:";
public static final String ENTRY_URN_PREFIX = "urn:entry:";
public static final String URN_SEPARATOR = ":";
public static final String CURVE_NAME = "secp256k1";
public static final String NS_URI = "http://trsst.com/spec/0.1";
public static final String NS_ABBR = "trsst";
public static final String SIGN = "sign";
public static final String ENCRYPT = "encrypt";
public static final String MENTION_URN = "urn:mention";
public static final String MENTION_URN_LEGACY = "urn:com.trsst.mention";
public static final String TAG_URN = "urn:tag";
public static final String TAG_URN_LEGACY = "urn:com.trsst.tag";
public static final String PREDECESSOR = "predecessor";
public static final String ATTACHMENT_DIGEST = "digest";
public static final String PREDECESSOR_ID = "id";
public static final String KEY_EXTENSION = ".p12";
public static final String VERB_DELETE = "delete";
public static final String VERB_DELETED = "deleted";
public static final String STAMP = "stamp";
public static final int STAMP_BITS = 20;
/**
* Default public rights are like CC ND BY but with added right of
* revocation. This lets you delete an entry and require takedown of that
* entry whereever it has been distributed.
*/
public static final String RIGHTS_NDBY_REVOCABLE = "attribution, no derivatives, revoked if deleted";
// "You may copy, distribute, display and perform only verbatim copies of
// the work, not derivative works based on it, and only if fully attributed
// to the author. Your license to the work is revoked worldwide if the
// author publicly deletes the original work.";
/**
* Default private rights are are explicity ARR if only to clearly
* differentiate private posts from public ones.
*/
public static final String RIGHTS_RESERVED = "all reserved";
private final static org.slf4j.Logger log;
static {
log = org.slf4j.LoggerFactory.getLogger(Common.class);
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (Throwable t) {
log.error(
"Could not initialize security provider: " + t.getMessage(),
t);
}
}
/**
* Hashes an elliptic curve public key into a shortened "satoshi-style"
* string that we use for a publicly-readable account id. Borrowed from
* bitsofproof.
*
* @param key
* the account EC public key.
* @return the account id
*/
public static String toFeedId(PublicKey key) {
byte[] keyDigest = keyHash(key.getEncoded());
byte[] addressBytes = new byte[keyDigest.length + 4];
// note: now leaving out BTC's first byte identifier
System.arraycopy(keyDigest, 0, addressBytes, 0, keyDigest.length);
byte[] check = hash(addressBytes, 0, keyDigest.length);
System.arraycopy(check, 0, addressBytes, keyDigest.length, 4);
return toBase58(addressBytes);
}
public static File getClientRoot() {
String path = System.getProperty("user.home", ".");
File root = new File(path, "trsstd");
path = System.getProperty("com.trsst.client.storage");
if (path != null) {
try {
root = new File(path);
root.mkdirs();
} catch (Throwable t) {
System.err.println("Invalid path: " + path + " : "
+ t.getMessage());
}
}
return root;
}
public static File getServerRoot() {
String path = System.getProperty("user.home", ".");
File root = new File(path, "trsstd");
path = System.getProperty("com.trsst.server.storage");
if (path != null) {
try {
root = new File(path);
root.mkdirs();
} catch (Throwable t) {
System.err.println("Invalid path: " + path + " : "
+ t.getMessage());
}
}
return root;
}
public static final String toFeedIdString(Object feedOrEntryUrn) {
String feedId = feedOrEntryUrn.toString();
if (feedId.startsWith(FEED_URN_PREFIX)) {
feedId = feedId.substring(FEED_URN_PREFIX.length());
} else if (feedId.startsWith(ENTRY_URN_PREFIX)) {
feedId = feedId.substring(ENTRY_URN_PREFIX.length());
feedId = feedId.substring(0, feedId.lastIndexOf(':'));
}
return feedId;
}
/**
* Returns the shorthand alias for a full alias uri, for example:
* 'acct:mpowers.trsst.com' becomes 'mpowers'.
*/
public static final String getShortAliasFromAliasUri(Object urn) {
String aliasUri = urn.toString();
if (aliasUri.indexOf(ACCOUNT_URN_PREFIX) == 0) {
aliasUri = aliasUri.substring(ACCOUNT_URN_PREFIX.length());
}
if (aliasUri.indexOf(ACCOUNT_PREFIX) == 0) {
aliasUri = aliasUri.substring(ACCOUNT_PREFIX.length());
}
int i;
// remove feed extension if any
i = aliasUri.indexOf(ACCOUNT_URN_FEED_PREFIX);
if (i != -1) {
aliasUri = aliasUri.substring(0, i);
}
// remove last domain extension if any
i = aliasUri.lastIndexOf(".");
if (i != -1) {
aliasUri = aliasUri.substring(0, i);
}
// do it again
i = aliasUri.lastIndexOf(".");
if (i != -1) {
aliasUri = aliasUri.substring(0, i);
}
return aliasUri;
}
/**
* Returns the associated feed, if any, from a full alias uri, for example:
* 'urn:acct:mpowers.trsst.com:feed:GhzsrQb7PmbvbdeG13Xr7VJiC59kSk4JW'
* becomes 'GhzsrQb7PmbvbdeG13Xr7VJiC59kSk4JW'.
*/
public static final String getFeedIdFromAliasUri(Object urn) {
// remove feed extension if any
String aliasUri = urn.toString();
int i = aliasUri.indexOf(ACCOUNT_URN_FEED_PREFIX);
if (i != -1) {
aliasUri = aliasUri.substring(i + 6);
}
return aliasUri;
}
public static final String toEntryIdString(Object entryUrn) {
String entryId = entryUrn.toString();
int i = entryId.lastIndexOf(URN_SEPARATOR);
if (i != -1) {
entryId = entryId.substring(i + 1);
}
if (entryId.startsWith(ENTRY_URN_PREFIX)) {
entryId = entryId.substring(ENTRY_URN_PREFIX.length());
}
return entryId;
}
public static final long toEntryId(Object entryUrn) {
return Long.parseLong(toEntryIdString(entryUrn), 16);
}
public static final long generateEntryId() {
try {
// sleep to ensure a unique id
// if creating multiple entries
Thread.sleep(3);
} catch (InterruptedException e) {
// should never ever happen
log.warn("generateEntryId: interrupted", e);
}
return System.currentTimeMillis();
}
public static final String toEntryUrn(String feedId, long entryId) {
return ENTRY_URN_PREFIX + feedId + URN_SEPARATOR
+ Long.toHexString(entryId);
}
public static final String fromFeedUrn(Object feedUrn) {
if (feedUrn != null) {
String feedId = feedUrn.toString();
if (feedId.startsWith(FEED_URN_PREFIX)) {
feedId = feedId.substring(9);
}
return feedId;
}
return null;
}
public static final String toFeedUrn(String feedId) {
if (feedId != null) {
if (!feedId.startsWith(FEED_URN_PREFIX)) {
feedId = FEED_URN_PREFIX + feedId;
}
}
return feedId;
}
public static final byte[] keyHash(byte[] key) {
try {
byte[] sha256 = MessageDigest.getInstance("SHA-256").digest(key);
return ripemd160(sha256);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static final byte[] ripemd160(byte[] data) {
byte[] ph = new byte[20];
RIPEMD160Digest digest = new RIPEMD160Digest();
digest.update(data, 0, data.length);
digest.doFinal(ph, 0);
return ph;
}
public static final byte[] hash(byte[] data, int offset, int len) {
try {
MessageDigest a = MessageDigest.getInstance("SHA-256");
a.update(data, offset, len);
return a.digest(a.digest());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static boolean isFeedId(String id) {
if (id.startsWith(FEED_URN_PREFIX)) {
id = id.substring(FEED_URN_PREFIX.length());
}
return (decodeChecked(id) != null);
}
public static boolean isExternalId(String id) {
// "external id" a.k.a. URL
try {
// test for valid url
id = fromFeedUrn(id);
new URL(decodeURL(id));
return true;
} catch (MalformedURLException e) {
return false;
}
}
public static boolean isAggregateId(String id) {
// "aggregate id" a.k.a. query result:
// currently, these start with a '?'.
id = fromFeedUrn(id);
return (id != null && id.length() > 0 && id.charAt(0) == '?');
}
/**
* Uses the checksum in the last 4 bytes of the decoded data to verify the
* rest are correct. The checksum is removed from the returned data. Returns
* null if invalid. Borrowed from bitcoinj.
*/
private static final byte[] decodeChecked(String input) {
byte tmp[];
try {
tmp = fromBase58(input);
} catch (IllegalArgumentException e) {
log.trace("decodeChecked: could not decode: " + input);
return null;
}
if (tmp.length < 4) {
log.trace("decodeChecked: input too short: " + input);
return null;
}
byte[] bytes = copyOfRange(tmp, 0, tmp.length - 4);
byte[] checksum = copyOfRange(tmp, tmp.length - 4, tmp.length);
tmp = doubleDigest(bytes, 0, bytes.length);
byte[] hash = copyOfRange(tmp, 0, 4);
if (!Arrays.equals(checksum, hash)) {
log.trace("decodeChecked: checksum does not validate: " + input);
return null;
}
log.trace("decodeChecked: input is valid: " + input);
return bytes;
}
private static final byte[] copyOfRange(byte[] source, int from, int to) {
byte[] range = new byte[to - from];
System.arraycopy(source, from, range, 0, range.length);
return range;
}
/**
* Calculates the SHA-256 hash of the given byte range, and then hashes the
* resulting hash again. This is standard procedure in Bitcoin. The
* resulting hash is in big endian form. Borrowed from bitcoinj.
*/
private static final byte[] doubleDigest(byte[] input, int offset,
int length) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
log.error(
"Should never happen: could not find SHA-256 MD algorithm",
e);
return null;
}
digest.reset();
digest.update(input, offset, length);
byte[] first = digest.digest();
return digest.digest(first);
}
/**
* Converts a X509-encoded EC key to a PublicKey.
*/
public static PublicKey toPublicKeyFromX509(String stored)
throws GeneralSecurityException {
KeyFactory factory = KeyFactory.getInstance("EC");
byte[] data = Base64.decodeBase64(stored);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
return factory.generatePublic(spec);
}
/**
* Converts an EC PublicKey to an X509-encoded string.
*/
public static String toX509FromPublicKey(PublicKey publicKey)
throws GeneralSecurityException {
KeyFactory factory = KeyFactory.getInstance("EC");
X509EncodedKeySpec spec = factory.getKeySpec(publicKey,
X509EncodedKeySpec.class);
return new Base64(0, null, true).encodeToString(spec.getEncoded());
}
static final KeyPair generateSigningKeyPair() {
try {
KeyPairGenerator kpg;
// kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg = new org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi.EC();
kpg.initialize(new ECGenParameterSpec(CURVE_NAME));
KeyPair kp = kpg.generateKeyPair();
return kp;
// } catch (NoSuchAlgorithmException e) {
// log.error("Error while generating key: " + e.getMessage(), e);
// } catch (NoSuchProviderException e) {
// log.error("Error while generating key: " + e.getMessage(), e);
} catch (InvalidAlgorithmParameterException e) {
log.error("Error while generating key: " + e.getMessage(), e);
}
return null;
}
static final KeyPair generateEncryptionKeyPair() {
try {
KeyPairGenerator kpg;
// kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg = new org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi.EC();
kpg.initialize(new ECGenParameterSpec(CURVE_NAME));
KeyPair kp = kpg.generateKeyPair();
return kp;
// } catch (NoSuchAlgorithmException e) {
// log.error("Error while generating key: " + e.getMessage(), e);
// } catch (NoSuchProviderException e) {
// e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
private static final char[] b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
.toCharArray();
private static final int[] r58 = new int[256];
static {
for (int i = 0; i < 256; ++i) {
r58[i] = -1;
}
for (int i = 0; i < b58.length; ++i) {
r58[b58[i]] = i;
}
}
public static String toBase58(byte[] b) {
if (b.length == 0) {
return "";
}
int lz = 0;
while (lz < b.length && b[lz] == 0) {
++lz;
}
StringBuffer s = new StringBuffer();
BigInteger n = new BigInteger(1, b);
while (n.compareTo(BigInteger.ZERO) > 0) {
BigInteger[] r = n.divideAndRemainder(BigInteger.valueOf(58));
n = r[0];
char digit = b58[r[1].intValue()];
s.append(digit);
}
while (lz > 0) {
--lz;
s.append("1");
}
return s.reverse().toString();
}
public static String toBase58WithChecksum(byte[] b) {
byte[] cs = Common.hash(b, 0, b.length);
byte[] extended = new byte[b.length + 4];
System.arraycopy(b, 0, extended, 0, b.length);
System.arraycopy(cs, 0, extended, b.length, 4);
return toBase58(extended);
}
public static byte[] fromBase58WithChecksum(String s) {
byte[] b = fromBase58(s);
if (b.length < 4) {
throw new IllegalArgumentException("Too short for checksum " + s);
}
byte[] cs = new byte[4];
System.arraycopy(b, b.length - 4, cs, 0, 4);
byte[] data = new byte[b.length - 4];
System.arraycopy(b, 0, data, 0, b.length - 4);
byte[] h = new byte[4];
System.arraycopy(hash(data, 0, data.length), 0, h, 0, 4);
if (Arrays.equals(cs, h)) {
return data;
}
throw new IllegalArgumentException("Checksum mismatch " + s);
}
public static byte[] fromBase58(String s) {
try {
boolean leading = true;
int lz = 0;
BigInteger b = BigInteger.ZERO;
for (char c : s.toCharArray()) {
if (leading && c == '1') {
++lz;
} else {
leading = false;
b = b.multiply(BigInteger.valueOf(58));
b = b.add(BigInteger.valueOf(r58[c]));
}
}
byte[] encoded = b.toByteArray();
if (encoded[0] == 0) {
if (lz > 0) {
--lz;
} else {
byte[] e = new byte[encoded.length - 1];
System.arraycopy(encoded, 1, e, 0, e.length);
encoded = e;
}
}
byte[] result = new byte[encoded.length + lz];
System.arraycopy(encoded, 0, result, lz, encoded.length);
return result;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Invalid character in address");
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static byte[] reverse(byte[] data) {
for (int i = 0, j = data.length - 1; i < data.length / 2; i++, j--) {
data[i] ^= data[j];
data[j] ^= data[i];
data[i] ^= data[j];
}
return data;
}
public static String toHex(byte[] data) {
try {
return new String(Hex.encode(data), "US-ASCII");
} catch (UnsupportedEncodingException e) {
}
return null;
}
public static byte[] fromHex(String hex) {
return Hex.decode(hex);
}
public static boolean isLessThanUnsigned(long n1, long n2) {
return (n1 < n2) ^ ((n1 < 0) != (n2 < 0));
}
public static byte[] readFully(InputStream data) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
int c;
byte[] buf = new byte[1024];
while ((c = data.read(buf)) != -1) {
output.write(buf, 0, c);
}
return output.toByteArray();
}
public static String encodeURL(String parameter) {
try {
return URLEncoder.encode(parameter, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("encodeURL: should never happen", e);
return null;
}
}
public static String decodeURL(String parameter) {
try {
return URLDecoder.decode(parameter, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("encodeURL: should never happen", e);
return null;
}
}
public static String escapeHTML(String html) {
return StringEscapeUtils.escapeHtml3(html);
}
public static String unescapeHTML(String escapedHtml) {
return StringEscapeUtils.unescapeHtml3(escapedHtml);
}
public static org.w3c.dom.Document fomToDom(Document<Element> doc) {
org.w3c.dom.Document dom = null;
if (doc != null) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
doc.writeTo(out);
ByteArrayInputStream in = new ByteArrayInputStream(
out.toByteArray());
DocumentBuilderFactory dbf = DocumentBuilderFactory
.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
dom = db.parse(in);
} catch (Exception e) {
}
}
return dom;
}
public static Document<Element> domToFom(org.w3c.dom.Document dom) {
Document<Element> doc = null;
if (dom != null) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new DOMSource(dom), new StreamResult(out));
ByteArrayInputStream in = new ByteArrayInputStream(
out.toByteArray());
doc = Abdera.getInstance().getParser().parse(in);
} catch (Exception e) {
}
}
return doc;
}
public static org.w3c.dom.Element fomToDom(Element element) {
org.w3c.dom.Element dom = null;
if (element != null) {
try {
ByteArrayInputStream in = new ByteArrayInputStream(element
.toString().getBytes());
DocumentBuilderFactory dbf = DocumentBuilderFactory
.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
dom = db.parse(in).getDocumentElement();
} catch (Exception e) {
}
}
return dom;
}
public static Element domToFom(org.w3c.dom.Element element) {
Element el = null;
if (element != null) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(new DOMSource(element), new StreamResult(out));
ByteArrayInputStream in = new ByteArrayInputStream(
out.toByteArray());
el = Abdera.getInstance().getParser().parse(in).getRoot();
} catch (Exception e) {
}
}
return el;
}
public static String formatXML(String xml) {
Tidy tidy = new Tidy();
tidy.setXmlTags(true);
tidy.setXmlOut(true);
StringWriter writer = new StringWriter();
tidy.parse(new StringReader(xml), writer);
return writer.toString();
}
public static Attributes getManifestAttributes() {
Attributes result = null;
Class<Common> clazz = Common.class;
String className = clazz.getSimpleName() + ".class";
URL classPath = clazz.getResource(className);
if (classPath == null || !classPath.toString().startsWith("jar")) {
// Class not from JAR
return null;
}
String classPathString = classPath.toString();
String manifestPath = classPathString.substring(0,
classPathString.lastIndexOf("!") + 1)
+ "/META-INF/MANIFEST.MF";
try {
Manifest manifest = new Manifest(new URL(manifestPath).openStream());
result = manifest.getMainAttributes();
} catch (MalformedURLException e) {
log.error("Could not locate manifest: " + manifestPath);
} catch (IOException e) {
log.error("Could not open manifest: " + manifestPath);
}
return result;
}
public static Date getBuildDate() {
Date result = null;
Attributes attributes = getManifestAttributes();
if (attributes != null) {
String dateString = attributes.getValue("Built-On");
try {
result = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.parse(dateString);
} catch (Throwable t) {
log.warn("Could not parse build timestamp: " + dateString);
}
} else {
log.warn("Could not find manifest attributes.");
}
return result;
}
public static String getBuildId() {
Attributes attributes = getManifestAttributes();
if (attributes != null) {
return attributes.getValue("Implementation-Build");
} else {
log.warn("Could not find manifest attributes.");
}
return null;
}
public static String getBuildString() {
String result = null;
String[] keys = new String[] { "Implementation-Title",
"Implementation-Version", "Implementation-Build", "Built-On", };
Attributes attributes = getManifestAttributes();
if (attributes != null) {
Object value;
for (String key : keys) {
value = attributes.getValue(key);
if (value != null) {
if (result == null) {
result = value.toString();
} else {
result = result + ' ' + value.toString();
}
}
}
} else {
result = "trsst client";
}
return result;
}
/**
* Most trsst nodes run with self-signed certificates, so by default we
* accept them. While posts are still signed and/or encrypted, a MITM can
* still refuse our out-going posts and suppress incoming new ones, but this
* the reason to relay with many trsst servers. Use the -strict option to
* require CA-signed certificates. Note that nowadays CA-signed certs are no
* guarantee either.
*/
public static void enableAnonymousSSL() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
}
} };
SSLContext sc;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
log.error("Can't get SSL context", e);
} catch (KeyManagementException e) {
log.error("Can't set SSL socket factory", e);
}
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
// For apache http client
Protocol anonhttps = new Protocol("https",
(ProtocolSocketFactory) new AnonymSSLSocketFactory(), 443); //
Protocol.registerProtocol("https", anonhttps);
}
}