1 package org.bouncycastle.crypto.macs;
2 
3 import org.bouncycastle.crypto.CipherParameters;
4 import org.bouncycastle.crypto.Digest;
5 import org.bouncycastle.crypto.Mac;
6 import org.bouncycastle.crypto.params.KeyParameter;
7 
8 /**
9  * HMAC implementation based on RFC2104
10  *
11  * H(K XOR opad, H(K XOR ipad, text))
12  */
13 public class OldHMac
14 implements Mac
15 {
16     private final static int BLOCK_LENGTH = 64;
17 
18     private final static byte IPAD = (byte)0x36;
19     private final static byte OPAD = (byte)0x5C;
20 
21     private Digest digest;
22     private int digestSize;
23     private byte[] inputPad = new byte[BLOCK_LENGTH];
24     private byte[] outputPad = new byte[BLOCK_LENGTH];
25 
26     /**
27      * @deprecated uses incorrect pad for SHA-512 and SHA-384 use HMac.
28      */
OldHMac( Digest digest)29     public OldHMac(
30         Digest digest)
31     {
32         this.digest = digest;
33         digestSize = digest.getDigestSize();
34     }
35 
getAlgorithmName()36     public String getAlgorithmName()
37     {
38         return digest.getAlgorithmName() + "/HMAC";
39     }
40 
getUnderlyingDigest()41     public Digest getUnderlyingDigest()
42     {
43         return digest;
44     }
45 
init( CipherParameters params)46     public void init(
47         CipherParameters params)
48     {
49         digest.reset();
50 
51         byte[] key = ((KeyParameter)params).getKey();
52 
53         if (key.length > BLOCK_LENGTH)
54         {
55             digest.update(key, 0, key.length);
56             digest.doFinal(inputPad, 0);
57             for (int i = digestSize; i < inputPad.length; i++)
58             {
59                 inputPad[i] = 0;
60             }
61         }
62         else
63         {
64             System.arraycopy(key, 0, inputPad, 0, key.length);
65             for (int i = key.length; i < inputPad.length; i++)
66             {
67                 inputPad[i] = 0;
68             }
69         }
70 
71         outputPad = new byte[inputPad.length];
72         System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
73 
74         for (int i = 0; i < inputPad.length; i++)
75         {
76             inputPad[i] ^= IPAD;
77         }
78 
79         for (int i = 0; i < outputPad.length; i++)
80         {
81             outputPad[i] ^= OPAD;
82         }
83 
84         digest.update(inputPad, 0, inputPad.length);
85     }
86 
getMacSize()87     public int getMacSize()
88     {
89         return digestSize;
90     }
91 
update( byte in)92     public void update(
93         byte in)
94     {
95         digest.update(in);
96     }
97 
update( byte[] in, int inOff, int len)98     public void update(
99         byte[] in,
100         int inOff,
101         int len)
102     {
103         digest.update(in, inOff, len);
104     }
105 
doFinal( byte[] out, int outOff)106     public int doFinal(
107         byte[] out,
108         int outOff)
109     {
110         byte[] tmp = new byte[digestSize];
111         digest.doFinal(tmp, 0);
112 
113         digest.update(outputPad, 0, outputPad.length);
114         digest.update(tmp, 0, tmp.length);
115 
116         int     len = digest.doFinal(out, outOff);
117 
118         reset();
119 
120         return len;
121     }
122 
123     /**
124      * Reset the mac generator.
125      */
reset()126     public void reset()
127     {
128         /*
129          * reset the underlying digest.
130          */
131         digest.reset();
132 
133         /*
134          * reinitialize the digest.
135          */
136         digest.update(inputPad, 0, inputPad.length);
137     }
138 }
139