History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/Mac.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/crypto/Mac.java+657−0
@@ -0,0 +1,657 @@
1+/*
2+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.crypto;
27+
28+import java.util.*;
29+
30+import java.security.*;
31+import java.security.Provider.Service;
32+import java.security.spec.AlgorithmParameterSpec;
33+
34+import java.nio.ByteBuffer;
35+
36+import sun.security.util.Debug;
37+import sun.security.jca.*;
38+import sun.security.jca.GetInstance.Instance;
39+
40+/**
41+ * This class provides the functionality of a "Message Authentication Code"
42+ * (MAC) algorithm.
43+ *
44+ * <p> A MAC provides a way to check
45+ * the integrity of information transmitted over or stored in an unreliable
46+ * medium, based on a secret key. Typically, message
47+ * authentication codes are used between two parties that share a secret
48+ * key in order to validate information transmitted between these
49+ * parties.
50+ *
51+ * <p> A MAC mechanism that is based on cryptographic hash functions is
52+ * referred to as HMAC. HMAC can be used with any cryptographic hash function,
53+ * e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is
54+ * specified in RFC 2104.
55+ *
56+ * <p> Every implementation of the Java platform is required to support
57+ * the following standard <code>Mac</code> algorithms:
58+ * <ul>
59+ * <li><tt>HmacMD5</tt></li>
60+ * <li><tt>HmacSHA1</tt></li>
61+ * <li><tt>HmacSHA256</tt></li>
62+ * </ul>
63+ * These algorithms are described in the
64+ * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
65+ * Mac section</a> of the
66+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
67+ * Consult the release documentation for your implementation to see if any
68+ * other algorithms are supported.
69+ *
70+ * @author Jan Luehe
71+ *
72+ * @since 1.4
73+ */
74+
75+public class Mac implements Cloneable {
76+
77+ private static final Debug debug =
78+ Debug.getInstance("jca", "Mac");
79+
80+ // The provider
81+ private Provider provider;
82+
83+ // The provider implementation (delegate)
84+ private MacSpi spi;
85+
86+ // The name of the MAC algorithm.
87+ private final String algorithm;
88+
89+ // Has this object been initialized?
90+ private boolean initialized = false;
91+
92+ // next service to try in provider selection
93+ // null once provider is selected
94+ private Service firstService;
95+
96+ // remaining services to try in provider selection
97+ // null once provider is selected
98+ private Iterator serviceIterator;
99+
100+ private final Object lock;
101+
102+ /**
103+ * Creates a MAC object.
104+ *
105+ * @param macSpi the delegate
106+ * @param provider the provider
107+ * @param algorithm the algorithm
108+ */
109+ protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
110+ this.spi = macSpi;
111+ this.provider = provider;
112+ this.algorithm = algorithm;
113+ serviceIterator = null;
114+ lock = null;
115+ }
116+
117+ private Mac(Service s, Iterator t, String algorithm) {
118+ firstService = s;
119+ serviceIterator = t;
120+ this.algorithm = algorithm;
121+ lock = new Object();
122+ }
123+
124+ /**
125+ * Returns the algorithm name of this <code>Mac</code> object.
126+ *
127+ * <p>This is the same name that was specified in one of the
128+ * <code>getInstance</code> calls that created this
129+ * <code>Mac</code> object.
130+ *
131+ * @return the algorithm name of this <code>Mac</code> object.
132+ */
133+ public final String getAlgorithm() {
134+ return this.algorithm;
135+ }
136+
137+ /**
138+ * Returns a <code>Mac</code> object that implements the
139+ * specified MAC algorithm.
140+ *
141+ * <p> This method traverses the list of registered security Providers,
142+ * starting with the most preferred Provider.
143+ * A new Mac object encapsulating the
144+ * MacSpi implementation from the first
145+ * Provider that supports the specified algorithm is returned.
146+ *
147+ * <p> Note that the list of registered providers may be retrieved via
148+ * the {@link Security#getProviders() Security.getProviders()} method.
149+ *
150+ * @param algorithm the standard name of the requested MAC algorithm.
151+ * See the Mac section in the <a href=
152+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
153+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
154+ * for information about standard algorithm names.
155+ *
156+ * @return the new <code>Mac</code> object.
157+ *
158+ * @exception NoSuchAlgorithmException if no Provider supports a
159+ * MacSpi implementation for the
160+ * specified algorithm.
161+ *
162+ * @see java.security.Provider
163+ */
164+ public static final Mac getInstance(String algorithm)
165+ throws NoSuchAlgorithmException {
166+ List services = GetInstance.getServices("Mac", algorithm);
167+ // make sure there is at least one service from a signed provider
168+ Iterator t = services.iterator();
169+ while (t.hasNext()) {
170+ Service s = (Service)t.next();
171+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
172+ continue;
173+ }
174+ return new Mac(s, t, algorithm);
175+ }
176+ throw new NoSuchAlgorithmException
177+ ("Algorithm " + algorithm + " not available");
178+ }
179+
180+ /**
181+ * Returns a <code>Mac</code> object that implements the
182+ * specified MAC algorithm.
183+ *
184+ * <p> A new Mac object encapsulating the
185+ * MacSpi implementation from the specified provider
186+ * is returned. The specified provider must be registered
187+ * in the security provider list.
188+ *
189+ * <p> Note that the list of registered providers may be retrieved via
190+ * the {@link Security#getProviders() Security.getProviders()} method.
191+ *
192+ * @param algorithm the standard name of the requested MAC algorithm.
193+ * See the Mac section in the <a href=
194+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
195+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
196+ * for information about standard algorithm names.
197+ *
198+ * @param provider the name of the provider.
199+ *
200+ * @return the new <code>Mac</code> object.
201+ *
202+ * @exception NoSuchAlgorithmException if a MacSpi
203+ * implementation for the specified algorithm is not
204+ * available from the specified provider.
205+ *
206+ * @exception NoSuchProviderException if the specified provider is not
207+ * registered in the security provider list.
208+ *
209+ * @exception IllegalArgumentException if the <code>provider</code>
210+ * is null or empty.
211+ *
212+ * @see java.security.Provider
213+ */
214+ public static final Mac getInstance(String algorithm, String provider)
215+ throws NoSuchAlgorithmException, NoSuchProviderException {
216+ Instance instance = JceSecurity.getInstance
217+ ("Mac", MacSpi.class, algorithm, provider);
218+ return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
219+ }
220+
221+ /**
222+ * Returns a <code>Mac</code> object that implements the
223+ * specified MAC algorithm.
224+ *
225+ * <p> A new Mac object encapsulating the
226+ * MacSpi implementation from the specified Provider
227+ * object is returned. Note that the specified Provider object
228+ * does not have to be registered in the provider list.
229+ *
230+ * @param algorithm the standard name of the requested MAC algorithm.
231+ * See the Mac section in the <a href=
232+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
233+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
234+ * for information about standard algorithm names.
235+ *
236+ * @param provider the provider.
237+ *
238+ * @return the new <code>Mac</code> object.
239+ *
240+ * @exception NoSuchAlgorithmException if a MacSpi
241+ * implementation for the specified algorithm is not available
242+ * from the specified Provider object.
243+ *
244+ * @exception IllegalArgumentException if the <code>provider</code>
245+ * is null.
246+ *
247+ * @see java.security.Provider
248+ */
249+ public static final Mac getInstance(String algorithm, Provider provider)
250+ throws NoSuchAlgorithmException {
251+ Instance instance = JceSecurity.getInstance
252+ ("Mac", MacSpi.class, algorithm, provider);
253+ return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
254+ }
255+
256+ // max number of debug warnings to print from chooseFirstProvider()
257+ private static int warnCount = 10;
258+
259+ /**
260+ * Choose the Spi from the first provider available. Used if
261+ * delayed provider selection is not possible because init()
262+ * is not the first method called.
263+ */
264+ void chooseFirstProvider() {
265+ if ((spi != null) || (serviceIterator == null)) {
266+ return;
267+ }
268+ synchronized (lock) {
269+ if (spi != null) {
270+ return;
271+ }
272+ if (debug != null) {
273+ int w = --warnCount;
274+ if (w >= 0) {
275+ debug.println("Mac.init() not first method "
276+ + "called, disabling delayed provider selection");
277+ if (w == 0) {
278+ debug.println("Further warnings of this type will "
279+ + "be suppressed");
280+ }
281+ new Exception("Call trace").printStackTrace();
282+ }
283+ }
284+ Exception lastException = null;
285+ while ((firstService != null) || serviceIterator.hasNext()) {
286+ Service s;
287+ if (firstService != null) {
288+ s = firstService;
289+ firstService = null;
290+ } else {
291+ s = (Service)serviceIterator.next();
292+ }
293+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
294+ continue;
295+ }
296+ try {
297+ Object obj = s.newInstance(null);
298+ if (obj instanceof MacSpi == false) {
299+ continue;
300+ }
301+ spi = (MacSpi)obj;
302+ provider = s.getProvider();
303+ // not needed any more
304+ firstService = null;
305+ serviceIterator = null;
306+ return;
307+ } catch (NoSuchAlgorithmException e) {
308+ lastException = e;
309+ }
310+ }
311+ ProviderException e = new ProviderException
312+ ("Could not construct MacSpi instance");
313+ if (lastException != null) {
314+ e.initCause(lastException);
315+ }
316+ throw e;
317+ }
318+ }
319+
320+ private void chooseProvider(Key key, AlgorithmParameterSpec params)
321+ throws InvalidKeyException, InvalidAlgorithmParameterException {
322+ synchronized (lock) {
323+ if (spi != null) {
324+ spi.engineInit(key, params);
325+ return;
326+ }
327+ Exception lastException = null;
328+ while ((firstService != null) || serviceIterator.hasNext()) {
329+ Service s;
330+ if (firstService != null) {
331+ s = firstService;
332+ firstService = null;
333+ } else {
334+ s = (Service)serviceIterator.next();
335+ }
336+ // if provider says it does not support this key, ignore it
337+ if (s.supportsParameter(key) == false) {
338+ continue;
339+ }
340+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
341+ continue;
342+ }
343+ try {
344+ MacSpi spi = (MacSpi)s.newInstance(null);
345+ spi.engineInit(key, params);
346+ provider = s.getProvider();
347+ this.spi = spi;
348+ firstService = null;
349+ serviceIterator = null;
350+ return;
351+ } catch (Exception e) {
352+ // NoSuchAlgorithmException from newInstance()
353+ // InvalidKeyException from init()
354+ // RuntimeException (ProviderException) from init()
355+ if (lastException == null) {
356+ lastException = e;
357+ }
358+ }
359+ }
360+ // no working provider found, fail
361+ if (lastException instanceof InvalidKeyException) {
362+ throw (InvalidKeyException)lastException;
363+ }
364+ if (lastException instanceof InvalidAlgorithmParameterException) {
365+ throw (InvalidAlgorithmParameterException)lastException;
366+ }
367+ if (lastException instanceof RuntimeException) {
368+ throw (RuntimeException)lastException;
369+ }
370+ String kName = (key != null) ? key.getClass().getName() : "(null)";
371+ throw new InvalidKeyException
372+ ("No installed provider supports this key: "
373+ + kName, lastException);
374+ }
375+ }
376+
377+ /**
378+ * Returns the provider of this <code>Mac</code> object.
379+ *
380+ * @return the provider of this <code>Mac</code> object.
381+ */
382+ public final Provider getProvider() {
383+ chooseFirstProvider();
384+ return this.provider;
385+ }
386+
387+ /**
388+ * Returns the length of the MAC in bytes.
389+ *
390+ * @return the MAC length in bytes.
391+ */
392+ public final int getMacLength() {
393+ chooseFirstProvider();
394+ return spi.engineGetMacLength();
395+ }
396+
397+ /**
398+ * Initializes this <code>Mac</code> object with the given key.
399+ *
400+ * @param key the key.
401+ *
402+ * @exception InvalidKeyException if the given key is inappropriate for
403+ * initializing this MAC.
404+ */
405+ public final void init(Key key) throws InvalidKeyException {
406+ try {
407+ if (spi != null) {
408+ spi.engineInit(key, null);
409+ } else {
410+ chooseProvider(key, null);
411+ }
412+ } catch (InvalidAlgorithmParameterException e) {
413+ throw new InvalidKeyException("init() failed", e);
414+ }
415+ initialized = true;
416+ }
417+
418+ /**
419+ * Initializes this <code>Mac</code> object with the given key and
420+ * algorithm parameters.
421+ *
422+ * @param key the key.
423+ * @param params the algorithm parameters.
424+ *
425+ * @exception InvalidKeyException if the given key is inappropriate for
426+ * initializing this MAC.
427+ * @exception InvalidAlgorithmParameterException if the given algorithm
428+ * parameters are inappropriate for this MAC.
429+ */
430+ public final void init(Key key, AlgorithmParameterSpec params)
431+ throws InvalidKeyException, InvalidAlgorithmParameterException {
432+ if (spi != null) {
433+ spi.engineInit(key, params);
434+ } else {
435+ chooseProvider(key, params);
436+ }
437+ initialized = true;
438+ }
439+
440+ /**
441+ * Processes the given byte.
442+ *
443+ * @param input the input byte to be processed.
444+ *
445+ * @exception IllegalStateException if this <code>Mac</code> has not been
446+ * initialized.
447+ */
448+ public final void update(byte input) throws IllegalStateException {
449+ chooseFirstProvider();
450+ if (initialized == false) {
451+ throw new IllegalStateException("MAC not initialized");
452+ }
453+ spi.engineUpdate(input);
454+ }
455+
456+ /**
457+ * Processes the given array of bytes.
458+ *
459+ * @param input the array of bytes to be processed.
460+ *
461+ * @exception IllegalStateException if this <code>Mac</code> has not been
462+ * initialized.
463+ */
464+ public final void update(byte[] input) throws IllegalStateException {
465+ chooseFirstProvider();
466+ if (initialized == false) {
467+ throw new IllegalStateException("MAC not initialized");
468+ }
469+ if (input != null) {
470+ spi.engineUpdate(input, 0, input.length);
471+ }
472+ }
473+
474+ /**
475+ * Processes the first <code>len</code> bytes in <code>input</code>,
476+ * starting at <code>offset</code> inclusive.
477+ *
478+ * @param input the input buffer.
479+ * @param offset the offset in <code>input</code> where the input starts.
480+ * @param len the number of bytes to process.
481+ *
482+ * @exception IllegalStateException if this <code>Mac</code> has not been
483+ * initialized.
484+ */
485+ public final void update(byte[] input, int offset, int len)
486+ throws IllegalStateException {
487+ chooseFirstProvider();
488+ if (initialized == false) {
489+ throw new IllegalStateException("MAC not initialized");
490+ }
491+
492+ if (input != null) {
493+ if ((offset < 0) || (len > (input.length - offset)) || (len < 0))
494+ throw new IllegalArgumentException("Bad arguments");
495+ spi.engineUpdate(input, offset, len);
496+ }
497+ }
498+
499+ /**
500+ * Processes <code>input.remaining()</code> bytes in the ByteBuffer
501+ * <code>input</code>, starting at <code>input.position()</code>.
502+ * Upon return, the buffer's position will be equal to its limit;
503+ * its limit will not have changed.
504+ *
505+ * @param input the ByteBuffer
506+ *
507+ * @exception IllegalStateException if this <code>Mac</code> has not been
508+ * initialized.
509+ * @since 1.5
510+ */
511+ public final void update(ByteBuffer input) {
512+ chooseFirstProvider();
513+ if (initialized == false) {
514+ throw new IllegalStateException("MAC not initialized");
515+ }
516+ if (input == null) {
517+ throw new IllegalArgumentException("Buffer must not be null");
518+ }
519+ spi.engineUpdate(input);
520+ }
521+
522+ /**
523+ * Finishes the MAC operation.
524+ *
525+ * <p>A call to this method resets this <code>Mac</code> object to the
526+ * state it was in when previously initialized via a call to
527+ * <code>init(Key)</code> or
528+ * <code>init(Key, AlgorithmParameterSpec)</code>.
529+ * That is, the object is reset and available to generate another MAC from
530+ * the same key, if desired, via new calls to <code>update</code> and
531+ * <code>doFinal</code>.
532+ * (In order to reuse this <code>Mac</code> object with a different key,
533+ * it must be reinitialized via a call to <code>init(Key)</code> or
534+ * <code>init(Key, AlgorithmParameterSpec)</code>.
535+ *
536+ * @return the MAC result.
537+ *
538+ * @exception IllegalStateException if this <code>Mac</code> has not been
539+ * initialized.
540+ */
541+ public final byte[] doFinal() throws IllegalStateException {
542+ chooseFirstProvider();
543+ if (initialized == false) {
544+ throw new IllegalStateException("MAC not initialized");
545+ }
546+ byte[] mac = spi.engineDoFinal();
547+ spi.engineReset();
548+ return mac;
549+ }
550+
551+ /**
552+ * Finishes the MAC operation.
553+ *
554+ * <p>A call to this method resets this <code>Mac</code> object to the
555+ * state it was in when previously initialized via a call to
556+ * <code>init(Key)</code> or
557+ * <code>init(Key, AlgorithmParameterSpec)</code>.
558+ * That is, the object is reset and available to generate another MAC from
559+ * the same key, if desired, via new calls to <code>update</code> and
560+ * <code>doFinal</code>.
561+ * (In order to reuse this <code>Mac</code> object with a different key,
562+ * it must be reinitialized via a call to <code>init(Key)</code> or
563+ * <code>init(Key, AlgorithmParameterSpec)</code>.
564+ *
565+ * <p>The MAC result is stored in <code>output</code>, starting at
566+ * <code>outOffset</code> inclusive.
567+ *
568+ * @param output the buffer where the MAC result is stored
569+ * @param outOffset the offset in <code>output</code> where the MAC is
570+ * stored
571+ *
572+ * @exception ShortBufferException if the given output buffer is too small
573+ * to hold the result
574+ * @exception IllegalStateException if this <code>Mac</code> has not been
575+ * initialized.
576+ */
577+ public final void doFinal(byte[] output, int outOffset)
578+ throws ShortBufferException, IllegalStateException
579+ {
580+ chooseFirstProvider();
581+ if (initialized == false) {
582+ throw new IllegalStateException("MAC not initialized");
583+ }
584+ int macLen = getMacLength();
585+ if (output == null || output.length-outOffset < macLen) {
586+ throw new ShortBufferException
587+ ("Cannot store MAC in output buffer");
588+ }
589+ byte[] mac = doFinal();
590+ System.arraycopy(mac, 0, output, outOffset, macLen);
591+ return;
592+ }
593+
594+ /**
595+ * Processes the given array of bytes and finishes the MAC operation.
596+ *
597+ * <p>A call to this method resets this <code>Mac</code> object to the
598+ * state it was in when previously initialized via a call to
599+ * <code>init(Key)</code> or
600+ * <code>init(Key, AlgorithmParameterSpec)</code>.
601+ * That is, the object is reset and available to generate another MAC from
602+ * the same key, if desired, via new calls to <code>update</code> and
603+ * <code>doFinal</code>.
604+ * (In order to reuse this <code>Mac</code> object with a different key,
605+ * it must be reinitialized via a call to <code>init(Key)</code> or
606+ * <code>init(Key, AlgorithmParameterSpec)</code>.
607+ *
608+ * @param input data in bytes
609+ * @return the MAC result.
610+ *
611+ * @exception IllegalStateException if this <code>Mac</code> has not been
612+ * initialized.
613+ */
614+ public final byte[] doFinal(byte[] input) throws IllegalStateException
615+ {
616+ chooseFirstProvider();
617+ if (initialized == false) {
618+ throw new IllegalStateException("MAC not initialized");
619+ }
620+ update(input);
621+ return doFinal();
622+ }
623+
624+ /**
625+ * Resets this <code>Mac</code> object.
626+ *
627+ * <p>A call to this method resets this <code>Mac</code> object to the
628+ * state it was in when previously initialized via a call to
629+ * <code>init(Key)</code> or
630+ * <code>init(Key, AlgorithmParameterSpec)</code>.
631+ * That is, the object is reset and available to generate another MAC from
632+ * the same key, if desired, via new calls to <code>update</code> and
633+ * <code>doFinal</code>.
634+ * (In order to reuse this <code>Mac</code> object with a different key,
635+ * it must be reinitialized via a call to <code>init(Key)</code> or
636+ * <code>init(Key, AlgorithmParameterSpec)</code>.
637+ */
638+ public final void reset() {
639+ chooseFirstProvider();
640+ spi.engineReset();
641+ }
642+
643+ /**
644+ * Returns a clone if the provider implementation is cloneable.
645+ *
646+ * @return a clone if the provider implementation is cloneable.
647+ *
648+ * @exception CloneNotSupportedException if this is called on a
649+ * delegate that does not support <code>Cloneable</code>.
650+ */
651+ public final Object clone() throws CloneNotSupportedException {
652+ chooseFirstProvider();
653+ Mac that = (Mac)super.clone();
654+ that.spi = (MacSpi)this.spi.clone();
655+ return that;
656+ }
657+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t