001package com.hfg.util; 002 003import java.io.File; 004import java.io.FileOutputStream; 005import java.io.OutputStream; 006import java.nio.file.Files; 007import java.security.KeyFactory; 008import java.security.KeyPair; 009import java.security.KeyPairGenerator; 010import java.security.PrivateKey; 011import java.security.PublicKey; 012import java.security.Signature; 013import java.security.spec.ECGenParameterSpec; 014import java.security.spec.PKCS8EncodedKeySpec; 015import java.security.spec.X509EncodedKeySpec; 016 017//------------------------------------------------------------------------------ 018/** 019 Cryptology-related methods for key & signature handling. 020 <div> 021 @author J. Alex Taylor, hairyfatguy.com 022 </div> 023 */ 024//------------------------------------------------------------------------------ 025// com.hfg XML/HTML Coding Library 026// 027// This library is free software; you can redistribute it and/or 028// modify it under the terms of the GNU Lesser General Public 029// License as published by the Free Software Foundation; either 030// version 2.1 of the License, or (at your option) any later version. 031// 032// This library is distributed in the hope that it will be useful, 033// but WITHOUT ANY WARRANTY; without even the implied warranty of 034// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 035// Lesser General Public License for more details. 036// 037// You should have received a copy of the GNU Lesser General Public 038// License along with this library; if not, write to the Free Software 039// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 040// 041// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 042// jataylor@hairyfatguy.com 043//------------------------------------------------------------------------------ 044 045public class CryptoUtil 046{ 047 048 private static String sDefaultEllipticCurveSpec = "secp521r1"; 049 050 //--------------------------------------------------------------------------- 051 /** 052 * Sets the default SunEC-implemented elliptic curve spec used. 053 * Surely there is a better way to find the possible values but here is one url: 054 * <a href='http://www.docjar.com/html/api/sun/security/ec/SunECEntries.java.html'> 055 * http://www.docjar.com/html/api/sun/security/ec/SunECEntries.java.html</a>. 056 * Also see "Implementing ECC with Java Standard Edition 7" by V. Martinez. 057 * @param inValue String spec for the SunEC-implemented elliptic curve to use. 058 */ 059 public static void setDefaultEllipticCurveSpec(String inValue) 060 { 061 sDefaultEllipticCurveSpec = inValue; 062 } 063 064 //--------------------------------------------------------------------------- 065 /** 066 * Returns the default SunEC-implemented elliptic curve spec used. 067 * @return Default String spec for the SunEC-implemented elliptic curve to use 068 */ 069 public static String getDefaultEllipticCurveSpec() 070 { 071 return sDefaultEllipticCurveSpec; 072 } 073 074 //--------------------------------------------------------------------------- 075 /** 076 * Generates an Elliptic Curve key pair using the default elliptic curve spec. 077 * @return KeyPair which can be written out to public and private key files. 078 * @throws Exception 079 */ 080 public static KeyPair generateEllipticCurveKeyPair() 081 throws Exception 082 { 083 return generateEllipticCurveKeyPair(sDefaultEllipticCurveSpec); 084 } 085 086 //--------------------------------------------------------------------------- 087 /** 088 * Generates an Elliptic Curve key pair. 089 * @param inEllipticCurveSpec String spec for the SunEC-implemented elliptic curve to use. 090 * @return KeyPair which can be written out to public and private key files. 091 * @throws Exception 092 */ 093 public static KeyPair generateEllipticCurveKeyPair(String inEllipticCurveSpec) 094 throws Exception 095 { 096 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "SunEC"); 097 098 keyPairGenerator.initialize(new ECGenParameterSpec(inEllipticCurveSpec)); 099 100 return keyPairGenerator.genKeyPair(); 101 } 102 103 //--------------------------------------------------------------------------- 104 public static void writePrivateEllipticCurveKeyToFile(PrivateKey inPrivateKey, File inFile) 105 throws Exception 106 { 107 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(inPrivateKey.getEncoded()); 108 109 OutputStream fileStream = null; 110 try 111 { 112 fileStream = new FileOutputStream(inFile); 113 fileStream.write(pkcs8EncodedKeySpec.getEncoded()); 114 } 115 finally 116 { 117 if (fileStream != null) 118 { 119 fileStream.close(); 120 } 121 } 122 } 123 124 //--------------------------------------------------------------------------- 125 public static PrivateKey readPrivateEllipticCurveKeyFile(File inPrivateKeyFile) 126 throws Exception 127 { 128 byte[] data = Files.readAllBytes(inPrivateKeyFile.toPath()); 129 130 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(data); 131 KeyFactory factory = KeyFactory.getInstance("EC"); 132 return factory.generatePrivate(spec); 133 } 134 135 //--------------------------------------------------------------------------- 136 public static void writePublicEllipticCurveKeyToFile(PublicKey inPublicKey, File inFile) 137 throws Exception 138 { 139 X509EncodedKeySpec spec = new X509EncodedKeySpec(inPublicKey.getEncoded()); 140 141 OutputStream fileStream = null; 142 try 143 { 144 fileStream = new FileOutputStream(inFile); 145 fileStream.write(spec.getEncoded()); 146 } 147 finally 148 { 149 if (fileStream != null) 150 { 151 fileStream.close(); 152 } 153 } 154 } 155 156 //--------------------------------------------------------------------------- 157 public static PublicKey readPublicEllipticCurveKeyFile(File inPublicKeyFile) 158 throws Exception 159 { 160 byte[] data = Files.readAllBytes(inPublicKeyFile.toPath()); 161 162 X509EncodedKeySpec spec = new X509EncodedKeySpec(data); 163 KeyFactory factory = KeyFactory.getInstance("EC"); 164 return factory.generatePublic(spec); 165 } 166 167 //--------------------------------------------------------------------------- 168 /** 169 * Generates a signature give a private key and the text to sign. 170 * Uses the SHA512withECDSA signature algorithm. 171 * @param inPrivateKey private Elliptic Curve key 172 * @param inText text to sign 173 * @return signature as a byte[] 174 * @throws Exception 175 */ 176 public static byte[] generateSignatureWithECDSA(PrivateKey inPrivateKey, String inText) 177 throws Exception 178 { 179 Signature signature = Signature.getInstance("SHA512withECDSA", "SunEC"); 180 signature.initSign(inPrivateKey); 181 182 signature.update(inText.getBytes()); 183 184 return signature.sign(); 185 } 186 187 //--------------------------------------------------------------------------- 188 /** 189 * Verifies a signature give a public key, the signed text, and the signature. 190 * Uses the SHA512withECDSA signature algorithm. 191 * @param inPublicKey public Elliptic Curve key 192 * @param inText text that was signed 193 * @param inSignature signature as a byte[] 194 * @return whether the signature is valid 195 * @throws Exception 196 */ 197 public static boolean verifySignatureWithECDSA(PublicKey inPublicKey, String inText, byte[] inSignature) 198 throws Exception 199 { 200 Signature signature = Signature.getInstance("SHA512withECDSA", "SunEC"); 201 signature.initVerify(inPublicKey); 202 203 signature.update(inText.getBytes()); 204 205 return signature.verify(inSignature); 206 } 207}