001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015-2016 ForgeRock AS. 015 */ 016 017package org.forgerock.util; 018 019import java.security.InvalidKeyException; 020import java.security.NoSuchAlgorithmException; 021import java.security.PrivateKey; 022import java.security.PublicKey; 023import java.security.Signature; 024import java.security.SignatureException; 025import java.security.cert.X509Certificate; 026import java.text.MessageFormat; 027 028/** 029 * Utility class for signing and verifying signatures. 030 */ 031public final class SignatureUtil { 032 033 /** 034 * Singleton approach by using a static inner class. 035 */ 036 private static final class SingletonHolder { 037 private static final SignatureUtil INSTANCE = new SignatureUtil(); 038 } 039 040 /** 041 * Private constructor to ensure SignatureUtil remains a Singleton. 042 */ 043 private SignatureUtil() { 044 } 045 046 /** 047 * Gets the SignatureUtil instance. 048 * 049 * @return The SignatureUtil singleton instance. 050 */ 051 public static SignatureUtil getInstance() { 052 return SingletonHolder.INSTANCE; 053 } 054 055 /** 056 * Signs a String using the given private key. Uses the algorithm from the 057 * private key to perform the signature. 058 * 059 * @param privateKey 060 * The private key to use to sign the String. 061 * @param algorithm 062 * The algorithm to use in the signing. 063 * @param message 064 * The String to sign. 065 * @return The byte array of the signature. 066 * @throws java.security.SignatureException 067 * If there is a problem when performing the signature. 068 */ 069 public byte[] sign(PrivateKey privateKey, String algorithm, String message) 070 throws SignatureException { 071 try { 072 Signature signature = Signature.getInstance(algorithm); 073 signature.initSign(privateKey); 074 signature.update(message.getBytes()); 075 return signature.sign(); 076 } catch (NoSuchAlgorithmException e) { 077 throw new SignatureException(MessageFormat.format( 078 "Could not get Signature instance with the algorithm: {0}", algorithm), e); 079 } catch (InvalidKeyException e) { 080 throw new SignatureException("Invalid key", e); 081 } 082 } 083 084 /** 085 * Verifies a signature of a String using the certificate. Uses the 086 * algorithm from the certificate to perform the verification of the 087 * signature. 088 * 089 * @param certificate 090 * The X509Certificate to use to verify the signature. 091 * @param algorithm 092 * The algorithm to use in the signing. 093 * @param message 094 * The String that was signed. 095 * @param signatureData 096 * The byte array of the signature. 097 * @return Whether or not the signature is valid for the String that was 098 * signed. 099 * @throws java.security.SignatureException 100 * If there is a problem when verifying the signature. 101 */ 102 public boolean verify(X509Certificate certificate, String algorithm, String message, 103 byte[] signatureData) throws SignatureException { 104 return verify(certificate.getPublicKey(), algorithm, message, signatureData); 105 } 106 107 /** 108 * Verifies a signature of a String using the public key. Uses the algorithm 109 * from the public key to perform the verification of the signature. 110 * 111 * @param publicKey 112 * The public key to use to verify the signature. 113 * @param algorithm 114 * The algorithm to use in the signing. 115 * @param message 116 * The String that was signed. 117 * @param signatureData 118 * The byte array of the signature. 119 * @return Whether or not the signature is valid for the String that was 120 * signed. 121 * @throws java.security.SignatureException 122 * If there is a problem when verifying the signature. 123 */ 124 public boolean verify(PublicKey publicKey, String algorithm, String message, 125 byte[] signatureData) throws SignatureException { 126 try { 127 Signature signature = Signature.getInstance(algorithm); 128 signature.initVerify(publicKey); 129 signature.update(message.getBytes()); 130 return signature.verify(signatureData); 131 } catch (NoSuchAlgorithmException e) { 132 throw new SignatureException(MessageFormat.format( 133 "Could not get Signature instance with the algorithm: {0}", algorithm), e); 134 } catch (InvalidKeyException e) { 135 throw new SignatureException("Invalid key", e); 136 } 137 } 138}