All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for TLS and DTLS, including a provider for the JSSE.

There is a newer version: 1.70
Show newest version
package org.bouncycastle.tls.crypto.impl.bc;

import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;

import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.RuntimeCryptoException;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.agreement.srp.SRP6Client;
import org.bouncycastle.crypto.agreement.srp.SRP6Server;
import org.bouncycastle.crypto.agreement.srp.SRP6VerifierGenerator;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.NullDigest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.ARIAEngine;
import org.bouncycastle.crypto.engines.CamelliaEngine;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.engines.RC4Engine;
import org.bouncycastle.crypto.engines.RSABlindedEngine;
import org.bouncycastle.crypto.engines.SEEDEngine;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.modes.CCMBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.modes.OCBBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.SRP6GroupParameters;
import org.bouncycastle.crypto.prng.DigestRandomGenerator;
import org.bouncycastle.tls.AlertDescription;
import org.bouncycastle.tls.EncryptionAlgorithm;
import org.bouncycastle.tls.HashAlgorithm;
import org.bouncycastle.tls.NamedGroup;
import org.bouncycastle.tls.ProtocolVersion;
import org.bouncycastle.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.tls.TlsFatalAlert;
import org.bouncycastle.tls.TlsUtils;
import org.bouncycastle.tls.crypto.TlsCertificate;
import org.bouncycastle.tls.crypto.TlsCipher;
import org.bouncycastle.tls.crypto.TlsCryptoParameters;
import org.bouncycastle.tls.crypto.TlsDHConfig;
import org.bouncycastle.tls.crypto.TlsDHDomain;
import org.bouncycastle.tls.crypto.TlsECConfig;
import org.bouncycastle.tls.crypto.TlsECDomain;
import org.bouncycastle.tls.crypto.TlsHMAC;
import org.bouncycastle.tls.crypto.TlsHash;
import org.bouncycastle.tls.crypto.TlsMAC;
import org.bouncycastle.tls.crypto.TlsNonceGenerator;
import org.bouncycastle.tls.crypto.TlsSRP6Client;
import org.bouncycastle.tls.crypto.TlsSRP6Server;
import org.bouncycastle.tls.crypto.TlsSRP6VerifierGenerator;
import org.bouncycastle.tls.crypto.TlsSRPConfig;
import org.bouncycastle.tls.crypto.TlsSecret;
import org.bouncycastle.tls.crypto.impl.AbstractTlsCrypto;
import org.bouncycastle.tls.crypto.impl.TlsAEADCipher;
import org.bouncycastle.tls.crypto.impl.TlsAEADCipherImpl;
import org.bouncycastle.tls.crypto.impl.TlsBlockCipher;
import org.bouncycastle.tls.crypto.impl.TlsBlockCipherImpl;
import org.bouncycastle.tls.crypto.impl.TlsEncryptor;
import org.bouncycastle.tls.crypto.impl.TlsNullCipher;
import org.bouncycastle.util.Arrays;

/**
 * Class for providing cryptographic services for TLS based on implementations in the BC light-weight API.
 * 

* This class provides default implementations for everything. If you need to customise it, extend the class * and override the appropriate methods. *

*/ public class BcTlsCrypto extends AbstractTlsCrypto { private final SecureRandom entropySource; public BcTlsCrypto(SecureRandom entropySource) { this.entropySource = entropySource; } BcTlsSecret adoptLocalSecret(byte[] data) { return new BcTlsSecret(this, data); } public SecureRandom getSecureRandom() { return entropySource; } public TlsCertificate createCertificate(byte[] encoding) throws IOException { return new BcTlsCertificate(this, encoding); } protected TlsCipher createCipher(TlsCryptoParameters cryptoParams, int encryptionAlgorithm, int macAlgorithm) throws IOException { switch (encryptionAlgorithm) { case EncryptionAlgorithm._3DES_EDE_CBC: return createDESedeCipher(cryptoParams, macAlgorithm); case EncryptionAlgorithm.AES_128_CBC: return createAESCipher(cryptoParams, 16, macAlgorithm); case EncryptionAlgorithm.AES_128_CCM: // NOTE: Ignores macAlgorithm return createCipher_AES_CCM(cryptoParams, 16, 16); case EncryptionAlgorithm.AES_128_CCM_8: // NOTE: Ignores macAlgorithm return createCipher_AES_CCM(cryptoParams, 16, 8); case EncryptionAlgorithm.AES_128_GCM: // NOTE: Ignores macAlgorithm return createCipher_AES_GCM(cryptoParams, 16, 16); case EncryptionAlgorithm.AES_128_OCB_TAGLEN96: // NOTE: Ignores macAlgorithm return createCipher_AES_OCB(cryptoParams, 16, 12); case EncryptionAlgorithm.AES_256_CBC: return createAESCipher(cryptoParams, 32, macAlgorithm); case EncryptionAlgorithm.AES_256_CCM: // NOTE: Ignores macAlgorithm return createCipher_AES_CCM(cryptoParams, 32, 16); case EncryptionAlgorithm.AES_256_CCM_8: // NOTE: Ignores macAlgorithm return createCipher_AES_CCM(cryptoParams, 32, 8); case EncryptionAlgorithm.AES_256_GCM: // NOTE: Ignores macAlgorithm return createCipher_AES_GCM(cryptoParams, 32, 16); case EncryptionAlgorithm.AES_256_OCB_TAGLEN96: // NOTE: Ignores macAlgorithm return createCipher_AES_OCB(cryptoParams, 32, 12); case EncryptionAlgorithm.ARIA_128_CBC: return createARIACipher(cryptoParams, 16, macAlgorithm); case EncryptionAlgorithm.ARIA_128_GCM: // NOTE: Ignores macAlgorithm return createCipher_ARIA_GCM(cryptoParams, 16, 16); case EncryptionAlgorithm.ARIA_256_CBC: return createARIACipher(cryptoParams, 32, macAlgorithm); case EncryptionAlgorithm.ARIA_256_GCM: // NOTE: Ignores macAlgorithm return createCipher_ARIA_GCM(cryptoParams, 32, 16); case EncryptionAlgorithm.CAMELLIA_128_CBC: return createCamelliaCipher(cryptoParams, 16, macAlgorithm); case EncryptionAlgorithm.CAMELLIA_128_GCM: // NOTE: Ignores macAlgorithm return createCipher_Camellia_GCM(cryptoParams, 16, 16); case EncryptionAlgorithm.CAMELLIA_256_CBC: return createCamelliaCipher(cryptoParams, 32, macAlgorithm); case EncryptionAlgorithm.CAMELLIA_256_GCM: // NOTE: Ignores macAlgorithm return createCipher_Camellia_GCM(cryptoParams, 32, 16); case EncryptionAlgorithm.CHACHA20_POLY1305: // NOTE: Ignores macAlgorithm return createChaCha20Poly1305(cryptoParams); case EncryptionAlgorithm.NULL: return createNullCipher(cryptoParams, macAlgorithm); case EncryptionAlgorithm.SEED_CBC: return createSEEDCipher(cryptoParams, macAlgorithm); default: throw new TlsFatalAlert(AlertDescription.internal_error); } } public TlsDHDomain createDHDomain(TlsDHConfig dhConfig) { return new BcTlsDHDomain(this, dhConfig); } public TlsECDomain createECDomain(TlsECConfig ecConfig) { return new BcTlsECDomain(this, ecConfig); } protected TlsEncryptor createEncryptor(TlsCertificate certificate) throws IOException { BcTlsCertificate bcCert = BcTlsCertificate.convert(this, certificate); bcCert.validateKeyUsage(KeyUsage.keyEncipherment); final RSAKeyParameters pubKeyRSA = bcCert.getPubKeyRSA(); return new TlsEncryptor() { public byte[] encrypt(byte[] input, int inOff, int length) throws IOException { try { PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine()); encoding.init(true, new ParametersWithRandom(pubKeyRSA, getSecureRandom())); return encoding.processBlock(input, inOff, length); } catch (InvalidCipherTextException e) { /* * This should never happen, only during decryption. */ throw new TlsFatalAlert(AlertDescription.internal_error, e); } } }; } public TlsNonceGenerator createNonceGenerator(byte[] additionalSeedMaterial) { final DigestRandomGenerator nonceGen = new DigestRandomGenerator(createDigest(HashAlgorithm.sha256)); if (additionalSeedMaterial != null && additionalSeedMaterial.length > 0) { nonceGen.addSeedMaterial(additionalSeedMaterial); } byte[] seed = new byte[createDigest(HashAlgorithm.sha256).getDigestSize()]; entropySource.nextBytes(seed); nonceGen.addSeedMaterial(seed); return new TlsNonceGenerator() { public byte[] generateNonce(int size) { byte[] nonce = new byte[size]; nonceGen.nextBytes(nonce); return nonce; } }; } public boolean hasAllRawSignatureAlgorithms() { return true; } public boolean hasDHAgreement() { return true; } public boolean hasECDHAgreement() { return true; } public boolean hasEncryptionAlgorithm(int encryptionAlgorithm) { switch (encryptionAlgorithm) { case EncryptionAlgorithm.DES40_CBC: case EncryptionAlgorithm.DES_CBC: case EncryptionAlgorithm.IDEA_CBC: case EncryptionAlgorithm.RC2_CBC_40: case EncryptionAlgorithm.RC4_128: case EncryptionAlgorithm.RC4_40: return false; default: return true; } } public boolean hasHashAlgorithm(short hashAlgorithm) { return true; } public boolean hasMacAlgorithm(int macAlgorithm) { return true; } public boolean hasNamedGroup(int namedGroup) { return NamedGroup.refersToASpecificGroup(namedGroup); } public boolean hasRSAEncryption() { return true; } public boolean hasSignatureAlgorithm(int signatureAlgorithm) { return true; } public boolean hasSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) { return true; } public boolean hasSRPAuthentication() { return true; } public TlsSecret createSecret(byte[] data) { try { return adoptLocalSecret(Arrays.clone(data)); } finally { // TODO[tls-ops] Add this after checking all callers // if (data != null) // { // Arrays.fill(data, (byte)0); // } } } public TlsSecret generateRSAPreMasterSecret(ProtocolVersion version) { byte[] data = new byte[48]; entropySource.nextBytes(data); TlsUtils.writeVersion(version, data, 0); return adoptLocalSecret(data); } public Digest createDigest(short hashAlgorithm) { switch (hashAlgorithm) { case HashAlgorithm.none: return new NullDigest(); case HashAlgorithm.md5: return new MD5Digest(); case HashAlgorithm.sha1: return new SHA1Digest(); case HashAlgorithm.sha224: return new SHA224Digest(); case HashAlgorithm.sha256: return new SHA256Digest(); case HashAlgorithm.sha384: return new SHA384Digest(); case HashAlgorithm.sha512: return new SHA512Digest(); default: throw new IllegalArgumentException("unknown HashAlgorithm: " + HashAlgorithm.getText(hashAlgorithm)); } } public TlsHash createHash(short algorithm) { return new BcTlsHash(algorithm, createDigest(algorithm)); } private static class BcTlsHash implements TlsHash { private final short hashAlgorithm; private final Digest digest; BcTlsHash(short hashAlgorithm, Digest digest) { this.hashAlgorithm = hashAlgorithm; this.digest = digest; } public void update(byte[] data, int offSet, int length) { digest.update(data, offSet, length); } public byte[] calculateHash() { byte[] rv = new byte[digest.getDigestSize()]; digest.doFinal(rv, 0); return rv; } public Object clone() { return new BcTlsHash(hashAlgorithm, cloneDigest(hashAlgorithm, digest)); } public void reset() { digest.reset(); } } public static Digest cloneDigest(short hashAlgorithm, Digest hash) { switch (hashAlgorithm) { case HashAlgorithm.md5: return new MD5Digest((MD5Digest)hash); case HashAlgorithm.sha1: return new SHA1Digest((SHA1Digest)hash); case HashAlgorithm.sha224: return new SHA224Digest((SHA224Digest)hash); case HashAlgorithm.sha256: return new SHA256Digest((SHA256Digest)hash); case HashAlgorithm.sha384: return new SHA384Digest((SHA384Digest)hash); case HashAlgorithm.sha512: return new SHA512Digest((SHA512Digest)hash); default: throw new IllegalArgumentException("unknown HashAlgorithm: " + HashAlgorithm.getText(hashAlgorithm)); } } protected TlsCipher createAESCipher(TlsCryptoParameters cryptoParams, int cipherKeySize, int macAlgorithm) throws IOException { return new TlsBlockCipher(this, cryptoParams, new BlockOperator(createAESBlockCipher(), true), new BlockOperator(createAESBlockCipher(), false), createHMAC(macAlgorithm), createHMAC(macAlgorithm), cipherKeySize); } protected TlsCipher createARIACipher(TlsCryptoParameters cryptoParams, int cipherKeySize, int macAlgorithm) throws IOException { return new TlsBlockCipher(this, cryptoParams, new BlockOperator(createARIABlockCipher(), true), new BlockOperator(createARIABlockCipher(), false), createHMAC(macAlgorithm), createHMAC(macAlgorithm), cipherKeySize); } protected TlsCipher createCamelliaCipher(TlsCryptoParameters cryptoParams, int cipherKeySize, int macAlgorithm) throws IOException { return new TlsBlockCipher(this, cryptoParams, new BlockOperator(createCamelliaBlockCipher(), true), new BlockOperator(createCamelliaBlockCipher(), false), createHMAC(macAlgorithm), createHMAC(macAlgorithm), cipherKeySize); } protected TlsCipher createChaCha20Poly1305(TlsCryptoParameters cryptoParams) throws IOException { return new TlsAEADCipher(cryptoParams, new BcChaCha20Poly1305(true), new BcChaCha20Poly1305(false), 32, 16, TlsAEADCipher.NONCE_RFC7905); } protected TlsAEADCipher createCipher_AES_CCM(TlsCryptoParameters cryptoParams, int cipherKeySize, int macSize) throws IOException { return new TlsAEADCipher(cryptoParams, new AeadOperator(createAEADBlockCipher_AES_CCM(), true), new AeadOperator(createAEADBlockCipher_AES_CCM(), false), cipherKeySize, macSize); } protected TlsAEADCipher createCipher_AES_GCM(TlsCryptoParameters cryptoParams, int cipherKeySize, int macSize) throws IOException { return new TlsAEADCipher(cryptoParams, new AeadOperator(createAEADBlockCipher_AES_GCM(), true), new AeadOperator(createAEADBlockCipher_AES_GCM(), false), cipherKeySize, macSize); } protected TlsAEADCipher createCipher_AES_OCB(TlsCryptoParameters cryptoParams, int cipherKeySize, int macSize) throws IOException { return new TlsAEADCipher(cryptoParams, new AeadOperator(createAEADBlockCipher_AES_OCB(), true), new AeadOperator(createAEADBlockCipher_AES_OCB(), false), cipherKeySize, macSize, TlsAEADCipher.NONCE_RFC7905); } protected TlsAEADCipher createCipher_ARIA_GCM(TlsCryptoParameters cryptoParams, int cipherKeySize, int macSize) throws IOException { return new TlsAEADCipher(cryptoParams, new AeadOperator(createAEADBlockCipher_ARIA_GCM(), true), new AeadOperator(createAEADBlockCipher_ARIA_GCM(), false), cipherKeySize, macSize); } protected TlsAEADCipher createCipher_Camellia_GCM(TlsCryptoParameters cryptoParams, int cipherKeySize, int macSize) throws IOException { return new TlsAEADCipher(cryptoParams, new AeadOperator(createAEADBlockCipher_Camellia_GCM(), true), new AeadOperator(createAEADBlockCipher_Camellia_GCM(), false), cipherKeySize, macSize); } protected TlsBlockCipher createDESedeCipher(TlsCryptoParameters cryptoParams, int macAlgorithm) throws IOException { return new TlsBlockCipher(this, cryptoParams, new BlockOperator(createDESedeBlockCipher(), true), new BlockOperator(createDESedeBlockCipher(), false), createHMAC(macAlgorithm), createHMAC(macAlgorithm), 24); } protected TlsNullCipher createNullCipher(TlsCryptoParameters cryptoParams, int macAlgorithm) throws IOException { return new TlsNullCipher(cryptoParams, createHMAC(macAlgorithm), createHMAC(macAlgorithm)); } protected TlsBlockCipher createSEEDCipher(TlsCryptoParameters cryptoParams, int macAlgorithm) throws IOException { return new TlsBlockCipher(this, cryptoParams, new BlockOperator(createSEEDBlockCipher(), true), new BlockOperator(createSEEDBlockCipher(), false), createHMAC(macAlgorithm), createHMAC(macAlgorithm), 16); } protected BlockCipher createAESEngine() { return new AESEngine(); } protected BlockCipher createARIAEngine() { return new ARIAEngine(); } protected BlockCipher createCamelliaEngine() { return new CamelliaEngine(); } protected BlockCipher createAESBlockCipher() { return new CBCBlockCipher(createAESEngine()); } protected BlockCipher createARIABlockCipher() { return new CBCBlockCipher(createARIAEngine()); } protected AEADBlockCipher createAEADBlockCipher_AES_CCM() { return new CCMBlockCipher(createAESEngine()); } protected AEADBlockCipher createAEADBlockCipher_AES_GCM() { // TODO Consider allowing custom configuration of multiplier return new GCMBlockCipher(createAESEngine()); } protected AEADBlockCipher createAEADBlockCipher_AES_OCB() { return new OCBBlockCipher(createAESEngine(), createAESEngine()); } protected AEADBlockCipher createAEADBlockCipher_ARIA_GCM() { // TODO Consider allowing custom configuration of multiplier return new GCMBlockCipher(createARIAEngine()); } protected AEADBlockCipher createAEADBlockCipher_Camellia_GCM() { // TODO Consider allowing custom configuration of multiplier return new GCMBlockCipher(createCamelliaEngine()); } protected BlockCipher createCamelliaBlockCipher() { return new CBCBlockCipher(createCamelliaEngine()); } protected BlockCipher createDESedeBlockCipher() { return new CBCBlockCipher(new DESedeEngine()); } protected StreamCipher createRC4StreamCipher() { return new RC4Engine(); } protected BlockCipher createSEEDBlockCipher() { return new CBCBlockCipher(new SEEDEngine()); } public TlsHMAC createHMAC(int macAlgorithm) { return new HMacOperator(createDigest(TlsUtils.getHashAlgorithmForHMACAlgorithm(macAlgorithm))); } public TlsSRP6Client createSRP6Client(TlsSRPConfig srpConfig) { final SRP6Client srpClient = new SRP6Client(); BigInteger[] ng = srpConfig.getExplicitNG(); SRP6GroupParameters srpGroup= new SRP6GroupParameters(ng[0], ng[1]); srpClient.init(srpGroup, new SHA1Digest(), this.getSecureRandom()); return new TlsSRP6Client() { public BigInteger calculateSecret(BigInteger serverB) throws TlsFatalAlert { try { return srpClient.calculateSecret(serverB); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } } public BigInteger generateClientCredentials(byte[] srpSalt, byte[] identity, byte[] password) { return srpClient.generateClientCredentials(srpSalt, identity, password); } }; } public TlsSRP6Server createSRP6Server(TlsSRPConfig srpConfig, BigInteger srpVerifier) { final SRP6Server srpServer = new SRP6Server(); BigInteger[] ng = srpConfig.getExplicitNG(); SRP6GroupParameters srpGroup= new SRP6GroupParameters(ng[0], ng[1]); srpServer.init(srpGroup, srpVerifier, new SHA1Digest(), this.getSecureRandom()); return new TlsSRP6Server() { public BigInteger generateServerCredentials() { return srpServer.generateServerCredentials(); } public BigInteger calculateSecret(BigInteger clientA) throws IOException { try { return srpServer.calculateSecret(clientA); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } } }; } public TlsSRP6VerifierGenerator createSRP6VerifierGenerator(TlsSRPConfig srpConfig) { BigInteger[] ng = srpConfig.getExplicitNG(); final SRP6VerifierGenerator verifierGenerator = new SRP6VerifierGenerator(); verifierGenerator.init(ng[0], ng[1], new SHA1Digest()); return new TlsSRP6VerifierGenerator() { public BigInteger generateVerifier(byte[] salt, byte[] identity, byte[] password) { return verifierGenerator.generateVerifier(salt, identity, password); } }; } private class BlockOperator implements TlsBlockCipherImpl { private final boolean isEncrypting; private final BlockCipher cipher; private KeyParameter key; BlockOperator(BlockCipher cipher, boolean isEncrypting) { this.cipher = cipher; this.isEncrypting = isEncrypting; } public void setKey(byte[] key, int keyOff, int keyLen) { this.key = new KeyParameter(key, keyOff, keyLen); cipher.init(isEncrypting, new ParametersWithIV(this.key, new byte[cipher.getBlockSize()])); } public void init(byte[] iv, int ivOff, int ivLen) { cipher.init(isEncrypting, new ParametersWithIV(null, iv, ivOff, ivLen)); } public int doFinal(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) { int blockSize = cipher.getBlockSize(); for (int i = 0; i < inputLength; i += blockSize) { cipher.processBlock(input, inputOffset + i, output, outputOffset + i); } return inputLength; } public int getBlockSize() { return cipher.getBlockSize(); } } public class AeadOperator implements TlsAEADCipherImpl { private final boolean isEncrypting; private final AEADBlockCipher cipher; private KeyParameter key; public AeadOperator(AEADBlockCipher cipher, boolean isEncrypting) { this.cipher = cipher; this.isEncrypting = isEncrypting; } public void setKey(byte[] key, int keyOff, int keyLen) { this.key = new KeyParameter(key, keyOff, keyLen); } public void init(byte[] nonce, int macSize, byte[] additionalData) { cipher.init(isEncrypting, new AEADParameters(key, macSize * 8, nonce, additionalData)); } public int getOutputSize(int inputLength) { return cipher.getOutputSize(inputLength); } public int doFinal(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) { int len = cipher.processBytes(input, inputOffset, inputLength, output, outputOffset); try { return len + cipher.doFinal(output, outputOffset + len); } catch (InvalidCipherTextException e) { // TODO: throw new RuntimeCryptoException(e.toString()); } } } private class HMacOperator implements TlsHMAC { private final HMac hmac; HMacOperator(Digest digest) { this.hmac = new HMac(digest); } public void setKey(byte[] key, int keyOff, int keyLen) { hmac.init(new KeyParameter(key, keyOff, keyLen)); } public void update(byte[] input, int inOff, int length) { hmac.update(input, inOff, length); } public byte[] calculateMAC() { byte[] rv = new byte[hmac.getMacSize()]; hmac.doFinal(rv, 0); return rv; } public int getInternalBlockSize() { return ((ExtendedDigest)hmac.getUnderlyingDigest()).getByteLength(); } public int getMacLength() { return hmac.getMacSize(); } public void reset() { hmac.reset(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy