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