17c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/* 27c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Copyright (C) 2009 Google Inc. All rights reserved. 37c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 47c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Licensed under the Apache License, Version 2.0 (the "License"); 57c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * you may not use this file except in compliance with the License. 67c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * You may obtain a copy of the License at 77c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 87c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * http://www.apache.org/licenses/LICENSE-2.0 97c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Unless required by applicable law or agreed to in writing, software 117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * distributed under the License is distributed on an "AS IS" BASIS, 127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * See the License for the specific language governing permissions and 147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * limitations under the License. 157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpackage com.google.polo.pairing; 187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.exception.PoloException; 207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.math.BigInteger; 227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.security.cert.Certificate; 237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport javax.net.ssl.SSLPeerUnverifiedException; 257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport javax.net.ssl.SSLSession; 267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/** 287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Utility methods of general usefulness to the Polo library. 297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpublic class PoloUtil { 317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Returns the peer {@link Certificate} for an {@link SSLSession}. 347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws PoloException if the peer certificate could not be obtained 367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * from the {@link SSLSession}. 377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return the {@link Certificate} of the peer 387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static Certificate getPeerCert(SSLSession session) 407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throws PoloException { 417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet // Peer certificate 437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet Certificate[] certs = session.getPeerCertificates(); 447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (certs == null || certs.length < 1) { 457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new PoloException("No peer certificate."); 467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return certs[0]; 487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (SSLPeerUnverifiedException e) { 497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new PoloException(e); 507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Return the local {@link Certificate} for an {@link SSLSession}. 557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws PoloException if the local certificate could not be obtained 577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * from the {@link SSLSession} 587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return the {@link Certificate} of the peer 597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static Certificate getLocalCert(SSLSession session) 617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throws PoloException { 627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet Certificate[] certs = session.getLocalCertificates(); 637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (certs == null || certs.length < 1) { 647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new PoloException("No local certificate."); 657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return certs[0]; 677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Converts an array of bytes to a string of hexadecimal characters. 717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Leading null bytes are preserved in the output. 727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * <p> 737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * The input byte stream is assumed to be a positive, two's complement 747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * representation of an integer. The return value is the hexadecimal string 757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * representation of this value. 767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param bytes the bytes to convert 787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return the string representation 797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static String bytesToHexString(byte[] bytes) { 817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (bytes == null || bytes.length == 0) { 827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return ""; 837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet BigInteger bigint = new BigInteger(1, bytes); 857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet int formatLen = bytes.length * 2; 867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return String.format("%0" + formatLen + "x", bigint); 877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Converts a string of hex characters to a byte array. 917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param hexstr the string of hex characters 937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return a byte array representation 947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static byte[] hexStringToBytes(String hexstr) { 967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (hexstr == null || hexstr.length() == 0 || (hexstr.length() % 2) != 0) { 977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new IllegalArgumentException("Bad input string."); 987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet byte[] result = new byte[hexstr.length() / 2]; 1017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet for (int i=0; i < result.length; i++) { 1027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet result[i] = (byte) Integer.parseInt(hexstr.substring(2 * i, 2 * (i + 1)), 1037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 16); 1047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return result; 1067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Converts an integer value to the big endian 4-byte representation. 1107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static final byte[] intToBigEndianIntBytes(int intVal) { 1127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet byte[] outBuf = new byte[4]; 1137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outBuf[0] = (byte)((intVal >> 24) & 0xff); 1147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outBuf[1] = (byte)((intVal >> 16) & 0xff); 1157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outBuf[2] = (byte)((intVal >> 8) & 0xff); 1167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outBuf[3] = (byte)(intVal & 0xff); 1177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return outBuf; 1187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Converts a 4-byte array of bytes to an unsigned long value. 1227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static final long intBigEndianBytesToLong(byte[] input) { 1247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet assert (input.length == 4); 1257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet long ret = (long)(input[0]) & 0xff; 1267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret <<= 8; 1277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret |= (long)(input[1]) & 0xff; 1287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret <<= 8; 1297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret |= (long)(input[2]) & 0xff; 1307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret <<= 8; 1317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet ret |= (long)(input[3]) & 0xff; 1327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return ret; 1337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet} 136