1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
/* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. */ /* * $Id: DOMHMACSignatureMethod.java,v 1.17 2005/09/15 14:29:04 mullan Exp $ */ package org.jcp.xml.dsig.internal.dom; import javax.xml.crypto.*; import javax.xml.crypto.dsig.*; import javax.xml.crypto.dsig.spec.HMACParameterSpec; import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.spec.AlgorithmParameterSpec; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.Mac; import javax.crypto.SecretKey; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.jcp.xml.dsig.internal.MacOutputStream; /** * DOM-based implementation of HMAC SignatureMethod. * * @author Sean Mullan */ public final class DOMHMACSignatureMethod extends DOMSignatureMethod { private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); private Mac hmac; private int outputLength; /** * Creates a <code>DOMHMACSignatureMethod</code> with the specified params * * @param params algorithm-specific parameters (may be <code>null</code>) * @throws InvalidAlgorithmParameterException if params are inappropriate */ public DOMHMACSignatureMethod(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { super(SignatureMethod.HMAC_SHA1, params); hmac = Mac.getInstance("HmacSHA1"); } /** * Creates a <code>DOMHMACSignatureMethod</code> from an element. * * @param smElem a SignatureMethod element */ public DOMHMACSignatureMethod(Element smElem) throws MarshalException { super(smElem); try { hmac = Mac.getInstance("HmacSHA1"); } catch (NoSuchAlgorithmException nsae) { throw new MarshalException("HmacSHA1 Mac implementation not found"); } } protected void checkParams(SignatureMethodParameterSpec params) throws InvalidAlgorithmParameterException { if (params != null) { if (!(params instanceof HMACParameterSpec)) { throw new InvalidAlgorithmParameterException ("params must be of type HMACParameterSpec"); } outputLength = ((HMACParameterSpec) params).getOutputLength(); if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "Setting outputLength from HMACParameterSpec to: " + outputLength); } } else { outputLength = -1; } } protected SignatureMethodParameterSpec unmarshalParams(Element paramsElem) throws MarshalException { outputLength = new Integer (paramsElem.getFirstChild().getNodeValue()).intValue(); if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "unmarshalled outputLength: " + outputLength); } return new HMACParameterSpec(outputLength); } protected void marshalParams(Element parent, String prefix) throws MarshalException { Document ownerDoc = DOMUtils.getOwnerDocument(parent); Element hmacElem = DOMUtils.createElement(ownerDoc, "HMACOutputLength", XMLSignature.XMLNS, prefix); hmacElem.appendChild(ownerDoc.createTextNode (String.valueOf(outputLength))); parent.appendChild(hmacElem); } public boolean verify(Key key, DOMSignedInfo si, byte[] sig, XMLValidateContext context) throws InvalidKeyException, SignatureException, XMLSignatureException { if (key == null || si == null || sig == null) { throw new NullPointerException ("key, signedinfo or signature data can't be null"); } if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "outputLength = " + outputLength); } hmac.init((SecretKey) key); si.canonicalize(context, new MacOutputStream(hmac)); byte[] result = hmac.doFinal(); if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "resultLength = " + result.length); } if (outputLength != -1) { int byteLength = outputLength/8; if (result.length > byteLength) { byte[] truncated = new byte[byteLength]; System.arraycopy(result, 0, truncated, 0, byteLength); result = truncated; } } return MessageDigest.isEqual(sig, result); } public byte[] sign(Key key, DOMSignedInfo si, XMLSignContext context) throws InvalidKeyException, XMLSignatureException { if (key == null || si == null) { throw new NullPointerException(); } hmac.init((SecretKey) key); si.canonicalize(context, new MacOutputStream(hmac)); byte[] result = hmac.doFinal(); if (outputLength != -1) { int byteLength = outputLength/8; if (result.length > byteLength) { byte[] truncated = new byte[byteLength]; System.arraycopy(result, 0, truncated, 0, byteLength); result = truncated; } } return result; } public boolean paramsEqual(AlgorithmParameterSpec spec) { if (getParameterSpec() == spec) { return true; } if (!(spec instanceof HMACParameterSpec)) { return false; } HMACParameterSpec ospec = (HMACParameterSpec) spec; return (outputLength == ospec.getOutputLength()); } }