package org.apache.kerberos.kerb.crypto.key;
import org.apache.kerberos.kerb.KrbException;
import org.apache.kerberos.kerb.crypto.Nfold;
import org.apache.kerberos.kerb.crypto.enc.EncryptProvider;
public abstract class DkKeyMaker extends AbstractKeyMaker {
public DkKeyMaker(EncryptProvider encProvider) {
super(encProvider);
}
// DK(Key, Constant) = random-to-key(DR(Key, Constant))
public byte[] dk(byte[] key, byte[] constant) throws KrbException {
return random2Key(dr(key, constant));
}
/*
* K1 = E(Key, n-fold(Constant), initial-cipher-state)
* K2 = E(Key, K1, initial-cipher-state)
* K3 = E(Key, K2, initial-cipher-state)
* K4 = ...
* DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
*/
protected byte[] dr(byte[] key, byte[] constant) throws KrbException {
int blocksize = encProvider().blockSize();
int keyInuptSize = encProvider().keyInputSize();
byte[] keyBytes = new byte[keyInuptSize];
byte[] Ki;
if (constant.length != blocksize) {
Ki = Nfold.nfold(constant, blocksize);
} else {
Ki = new byte[constant.length];
System.arraycopy(constant, 0, Ki, 0, constant.length);
}
int n = 0, len;
while (n < keyInuptSize) {
encProvider().encrypt(key, Ki);
if (n + blocksize >= keyInuptSize) {
System.arraycopy(Ki, 0, keyBytes, n, keyInuptSize - n);
break;
}
System.arraycopy(Ki, 0, keyBytes, n, blocksize);
n += blocksize;
}
return keyBytes;
}
}