mirrored from https://www.bouncycastle.org/repositories/bc-java
/
ConcatenationKDFGenerator.java
129 lines (110 loc) · 3.22 KB
/
ConcatenationKDFGenerator.java
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
package org.bouncycastle.crypto.agreement.kdf;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.DerivationParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.KDFParameters;
/**
* Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1
*/
public class ConcatenationKDFGenerator
implements DerivationFunction
{
private Digest digest;
private byte[] shared;
private byte[] otherInfo;
private int hLen;
/**
* @param digest the digest to be used as the source of generated bytes
*/
public ConcatenationKDFGenerator(
Digest digest)
{
this.digest = digest;
this.hLen = digest.getDigestSize();
}
public void init(
DerivationParameters param)
{
if (param instanceof KDFParameters)
{
KDFParameters p = (KDFParameters)param;
shared = p.getSharedSecret();
otherInfo = p.getIV();
}
else
{
throw new IllegalArgumentException("KDF parameters required for generator");
}
}
/**
* return the underlying digest.
*/
public Digest getDigest()
{
return digest;
}
/**
* int to octet string.
*/
private void ItoOSP(
int i,
byte[] sp)
{
sp[0] = (byte)(i >>> 24);
sp[1] = (byte)(i >>> 16);
sp[2] = (byte)(i >>> 8);
sp[3] = (byte)(i >>> 0);
}
/**
* fill len bytes of the output buffer with bytes generated from
* the derivation function.
*
* @throws DataLengthException if the out buffer is too small.
*/
public int generateBytes(
byte[] out,
int outOff,
int len)
throws DataLengthException, IllegalArgumentException
{
if (len <= 0)
{
throw new IllegalArgumentException("len must be > 0");
}
if ((out.length - len) < outOff)
{
throw new OutputLengthException("output buffer too small");
}
byte[] hashBuf = new byte[hLen];
byte[] C = new byte[4];
int counter = 1;
int outputLen = 0;
digest.reset();
if (len > hLen)
{
do
{
ItoOSP(counter, C);
digest.update(C, 0, C.length);
digest.update(shared, 0, shared.length);
digest.update(otherInfo, 0, otherInfo.length);
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, hLen);
outputLen += hLen;
}
while ((counter++) < (len / hLen));
}
if (outputLen < len)
{
ItoOSP(counter, C);
digest.update(C, 0, C.length);
digest.update(shared, 0, shared.length);
digest.update(otherInfo, 0, otherInfo.length);
digest.doFinal(hashBuf, 0);
System.arraycopy(hashBuf, 0, out, outOff + outputLen, len - outputLen);
}
return len;
}
}