下面列出了javax.crypto.Mac#reset ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void addMAC(Mac writeMAC, int hashSize, long sequence_number) throws Exception {
byte[] tmp = payload;
payload = new byte[tmp.length + hashSize];
System.arraycopy(tmp, 0, payload, 0, tmp.length);
ByteArrayOutputStream macInput = new ByteArrayOutputStream();
macInput.write(Utils.getbytes64(sequence_number));
macInput.write(new byte[] {contentType, protocolVersion.getMajorVersion(), protocolVersion.getMinorVersion(), lengthMSB, lengthLSB});
macInput.write(tmp);
writeMAC.reset();
writeMAC.update(macInput.toByteArray());
writeMAC.doFinal(payload, payload.length - hashSize);
length = payload.length;
lengthMSB = (byte)(0xFF & (length >>> 8));
lengthLSB = (byte)(0xFF & length);
}
/**
* Constant-time equality check.
*/
private boolean safeEquals(ByteBuffer signature, byte[] calculatedSig) {
try {
signature.rewind();
Mac hmac = Mac.getInstance(hmacComparisonKey.getAlgorithm());
hmac.init(hmacComparisonKey);
hmac.update(signature);
byte[] signatureHash = hmac.doFinal();
hmac.reset();
hmac.update(calculatedSig);
byte[] calculatedHash = hmac.doFinal();
return MessageDigest.isEqual(signatureHash, calculatedHash);
} catch (GeneralSecurityException ex) {
// We've hardcoded these algorithms, so the error should not be possible.
throw new RuntimeException("Unexpected exception", ex);
}
}
/**
* Constant-time equality check.
*/
private boolean safeEquals(ByteBuffer signature, byte[] calculatedSig) {
try {
signature.rewind();
Mac hmac = Mac.getInstance(hmacComparisonKey.getAlgorithm());
hmac.init(hmacComparisonKey);
hmac.update(signature);
byte[] signatureHash = hmac.doFinal();
hmac.reset();
hmac.update(calculatedSig);
byte[] calculatedHash = hmac.doFinal();
return MessageDigest.isEqual(signatureHash, calculatedHash);
} catch (GeneralSecurityException ex) {
// We've hardcoded these algorithms, so the error should not be possible.
throw new RuntimeException("Unexpected exception", ex);
}
}
private boolean hmacEqual(byte[] sig, byte[] message, Key key) throws NoSuchAlgorithmException, InvalidKeyException {
// See https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
// This randomizes the byte order to make timing attacks more difficult.
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte[] calculatedSig = mac.doFinal(message);
// Generate a random key for use in comparison
byte[] randomKey = new byte[32];
RANDOM.nextBytes(randomKey);
// Then generate two HMACs for the different signatures found
Mac mac2 = Mac.getInstance("HmacSHA256");
mac2.init(new SecretKeySpec(randomKey, "HmacSHA256"));
byte[] clientSig = mac2.doFinal(sig);
mac2.reset();
byte[] realSig = mac2.doFinal(calculatedSig);
return MessageDigest.isEqual(clientSig, realSig);
}
private static byte[] P_hash(String transformation, byte[] secret, byte[] seed, Mac mac, int required) throws Exception {
byte[] out = new byte[required];
int offset = 0;
int toCopy;
byte[] A = seed;
byte[] tmp;
while (required > 0) {
SecretKeySpec key = new SecretKeySpec(secret, transformation);
mac.init(key);
mac.update(A);
A = mac.doFinal();
mac.reset();
mac.init(key);
mac.update(A);
mac.update(seed);
tmp = mac.doFinal();
toCopy = min(required, tmp.length);
System.arraycopy(tmp, 0, out, offset, toCopy);
offset += toCopy;
required -= toCopy;
}
return out;
}
@Override
public void doTest(String algo) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
Mac mac;
try {
mac = Mac.getInstance(algo, "SunJCE");
} catch (NoSuchAlgorithmException nsae) {
// depending on Solaris configuration,
// it can support HMAC or not with Mac
System.out.println("Expected NoSuchAlgorithmException thrown: "
+ nsae);
return;
}
byte[] plain = new byte[MESSAGE_SIZE];
for (int i = 0; i < MESSAGE_SIZE; i++) {
plain[i] = (byte) (i % 256);
}
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
SecretKeySpec keySpec = new SecretKeySpec(keyVal, "HMAC");
mac.init(keySpec);
byte[] result1 = mac.doFinal(plain);
mac.reset();
mac.update(plain[0]);
mac.update(plain, 1, OFFSET - 1);
byte[] result2 = mac.doFinal(tail);
if (!java.util.Arrays.equals(result1, result2)) {
throw new RuntimeException("result1 and result2 are not the same");
}
}
@Override
public void doTest(String algo) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException {
Mac mac;
try {
mac = Mac.getInstance(algo, "SunJCE");
} catch (NoSuchAlgorithmException nsae) {
// depending on Solaris configuration,
// it can support HMAC or not with Mac
System.out.println("Expected NoSuchAlgorithmException thrown: "
+ nsae);
return;
}
byte[] plain = new byte[MESSAGE_SIZE];
for (int i = 0; i < MESSAGE_SIZE; i++) {
plain[i] = (byte) (i % 256);
}
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
SecretKeySpec keySpec = new SecretKeySpec(keyVal, "HMAC");
mac.init(keySpec);
byte[] result1 = mac.doFinal(plain);
mac.reset();
mac.update(plain[0]);
mac.update(plain, 1, OFFSET - 1);
byte[] result2 = mac.doFinal(tail);
if (!java.util.Arrays.equals(result1, result2)) {
throw new RuntimeException("result1 and result2 are not the same");
}
}
public Keys(SecretKey encryptionKey, SecretKey integrityKey) throws InvalidKeyException {
this.encryptionKey = encryptionKey;
this.integrityKey = integrityKey;
// Forces early failure if any of the keys are not good.
// This allows us to spare callers from InvalidKeyException in several methods.
Mac hmac = DoubleClickCrypto.createMac();
hmac.init(encryptionKey);
hmac.reset();
hmac.init(integrityKey);
hmac.reset();
}
/**
* HKDF expand
*
* @param key a pseudo random key
* @param info context and application specific information
* @param outputLength length of output keying material in bytes
* @return output keying material
*/
static byte[] expand(byte[] key, byte[] info, int outputLength) {
AssertUtil.notNull(key, "key must not be null");
if (outputLength <= 0) {
throw new IllegalArgumentException("outputLength must be positive");
}
if (outputLength > 255 * HASH_LENGTH) {
throw new IllegalArgumentException("outputLength must be less than or equal to 255*HashLen");
}
if (info == null) {
info = new byte[0];
}
int n = (outputLength % HASH_LENGTH == 0) ?
outputLength / HASH_LENGTH :
(outputLength / HASH_LENGTH) + 1;
byte[] hashRound = new byte[0];
ByteBuffer generatedBytes = ByteBuffer.allocate(Math.multiplyExact(n, HASH_LENGTH));
Mac mac = createMac(key);
for (int roundNum = 1; roundNum <= n; roundNum++) {
mac.reset();
byte[] secret = ByteBuffer
.allocate(hashRound.length + info.length + 1)
.put(hashRound).put(info).put((byte) roundNum)
.array();
hashRound = mac.doFinal(secret);
generatedBytes.put(hashRound);
}
byte[] result = new byte[outputLength];
generatedBytes.rewind();
generatedBytes.get(result, 0, outputLength);
return result;
}
/**
* {@code payload = payload ^ hmac(encryptionKey, initVector || counterBytes)}
* per max-20-byte blocks.
*/
private void xorPayloadToHmacPad(byte[] workBytes) {
int payloadSize = workBytes.length - OVERHEAD_SIZE;
int sections = (payloadSize + COUNTER_PAGESIZE - 1) / COUNTER_PAGESIZE;
checkArgument(sections <= COUNTER_SECTIONS, "Payload is %s bytes, exceeds limit of %s",
payloadSize, COUNTER_PAGESIZE * COUNTER_SECTIONS);
Mac encryptionHmac = createMac();
byte[] pad = new byte[COUNTER_PAGESIZE + 3];
int counterSize = 0;
for (int section = 0; section < sections; ++section) {
int sectionBase = section * COUNTER_PAGESIZE;
int sectionSize = min(payloadSize - sectionBase, COUNTER_PAGESIZE);
try {
encryptionHmac.reset();
encryptionHmac.init(keys.getEncryptionKey());
encryptionHmac.update(workBytes, INITV_BASE, INITV_SIZE);
if (counterSize != 0) {
encryptionHmac.update(pad, COUNTER_PAGESIZE, counterSize);
}
encryptionHmac.doFinal(pad, 0);
} catch (ShortBufferException | InvalidKeyException e) {
throw new IllegalStateException(e);
}
for (int i = 0; i < sectionSize; ++i) {
workBytes[PAYLOAD_BASE + sectionBase + i] ^= pad[i];
}
Arrays.fill(pad, 0, COUNTER_PAGESIZE, (byte) 0);
if (counterSize == 0 || ++pad[COUNTER_PAGESIZE + counterSize - 1] == 0) {
++counterSize;
}
}
}
/**
* Uses a random generator to initialize a message, instantiate a Mac object
* according to the given PBMAC1 algorithm, initialize the object with a
* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
* feed the message into the Mac object all at once and get the output MAC
* as result1. Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param theMacAlgo PBMAC algorithm to test
* @param thePBKDF2Algo PBKDF2 algorithm to test
* @return true - the test is passed; false - otherwise.
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
int OFFSET = 5;
// Some message for which a MAC result will be calculated
byte[] plain = new byte[25];
new SecureRandom().nextBytes(plain);
// Form tail - is one of the three pieces
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
// Obtain a SecretKey using PBKDF2
SecretKey key = getSecretKey(thePBKDF2Algo);
// Instantiate Mac object and init it with a SecretKey and calc result1
Mac theMac = Mac.getInstance(theMacAlgo);
theMac.init(key);
byte[] result1 = theMac.doFinal(plain);
if (!isMacLengthExpected(theMacAlgo, result1.length)) {
return false;
}
// Reset Mac and calculate result2
theMac.reset();
theMac.update(plain[0]);
theMac.update(plain, 1, OFFSET - 1);
byte[] result2 = theMac.doFinal(tail);
// Return result
if (!java.util.Arrays.equals(result1, result2)) {
System.out.println("result1 and result2 are not the same:");
System.out.println("result1: " + dumpByteArray(result1));
System.out.println("result2: " + dumpByteArray(result2));
return false;
} else {
System.out.println("Resulted MAC with update and doFinal is same");
}
return true;
}
/**
* Uses a random generator to initialize a message, instantiate a Mac object
* according to the given PBMAC1 algorithm, initialize the object with a
* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
* feed the message into the Mac object all at once and get the output MAC
* as result1. Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param theMacAlgo PBMAC algorithm to test
* @param thePBKDF2Algo PBKDF2 algorithm to test
* @return true - the test is passed; false - otherwise.
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
int OFFSET = 5;
// Some message for which a MAC result will be calculated
byte[] plain = new byte[25];
new SecureRandom().nextBytes(plain);
// Form tail - is one of the three pieces
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
// Obtain a SecretKey using PBKDF2
SecretKey key = getSecretKey(thePBKDF2Algo);
// Instantiate Mac object and init it with a SecretKey and calc result1
Mac theMac = Mac.getInstance(theMacAlgo);
theMac.init(key);
byte[] result1 = theMac.doFinal(plain);
if (!isMacLengthExpected(theMacAlgo, result1.length)) {
return false;
}
// Reset Mac and calculate result2
theMac.reset();
theMac.update(plain[0]);
theMac.update(plain, 1, OFFSET - 1);
byte[] result2 = theMac.doFinal(tail);
// Return result
if (!java.util.Arrays.equals(result1, result2)) {
System.out.println("result1 and result2 are not the same:");
System.out.println("result1: " + dumpByteArray(result1));
System.out.println("result2: " + dumpByteArray(result2));
return false;
} else {
System.out.println("Resulted MAC with update and doFinal is same");
}
return true;
}
private void doTest(String algo, Provider provider)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException {
System.out.println("Test " + algo);
Mac mac;
try {
mac = Mac.getInstance(algo, provider);
} catch (NoSuchAlgorithmException nsae) {
if ("SunPKCS11-Solaris".equals(provider.getName())) {
// depending on Solaris configuration,
// it can support HMAC or not with Mac
System.out.println("Expected NoSuchAlgorithmException thrown: "
+ nsae);
return;
}
throw nsae;
}
byte[] plain = new byte[MESSAGE_SIZE];
for (int i = 0; i < MESSAGE_SIZE; i++) {
plain[i] = (byte) (i % 256);
}
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
SecureRandom srdm = new SecureRandom();
byte[] keyVal = new byte[KEY_SIZE];
srdm.nextBytes(keyVal);
SecretKeySpec keySpec = new SecretKeySpec(keyVal, "HMAC");
mac.init(keySpec);
byte[] result1 = mac.doFinal(plain);
mac.reset();
mac.update(plain[0]);
mac.update(plain, 1, OFFSET - 1);
byte[] result2 = mac.doFinal(tail);
if (!java.util.Arrays.equals(result1, result2)) {
throw new RuntimeException("result1 and result2 are not the same");
}
}
public byte[] build() {
Objects.requireNonNull(algorithm, "algorithm");
Objects.requireNonNull(scheme, "scheme");
Objects.requireNonNull(host, "host");
Objects.requireNonNull(method, "method");
Objects.requireNonNull(resource, "resource");
Objects.requireNonNull(contentType, "contentType");
Objects.requireNonNull(apiKey, "apiKey");
Objects.requireNonNull(date, "date");
Objects.requireNonNull(payload, "payload");
try {
final Mac digest = Mac.getInstance(algorithm);
SecretKeySpec secretKey = new SecretKeySpec(apiSecret, algorithm);
digest.init(secretKey);
digest.update(method.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(scheme.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(host.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(resource.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(contentType.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(apiKey.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
if (nonce != null) {
digest.update(nonce.getBytes(StandardCharsets.UTF_8));
}
digest.update(DELIMITER);
digest.update(date.getBytes(StandardCharsets.UTF_8));
digest.update(DELIMITER);
digest.update(payload);
digest.update(DELIMITER);
final byte[] signatureBytes = digest.doFinal();
digest.reset();
return signatureBytes;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Can't create signature: " + e.getMessage(), e);
}
}
/**
* Uses a random generator to initialize a message, instantiate a Mac object
* according to the given PBMAC1 algorithm, initialize the object with a
* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
* feed the message into the Mac object all at once and get the output MAC
* as result1. Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param theMacAlgo PBMAC algorithm to test
* @param thePBKDF2Algo PBKDF2 algorithm to test
* @return true - the test is passed; false - otherwise.
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
int OFFSET = 5;
// Some message for which a MAC result will be calculated
byte[] plain = new byte[25];
new SecureRandom().nextBytes(plain);
// Form tail - is one of the three pieces
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
// Obtain a SecretKey using PBKDF2
SecretKey key = getSecretKey(thePBKDF2Algo);
// Instantiate Mac object and init it with a SecretKey and calc result1
Mac theMac = Mac.getInstance(theMacAlgo);
theMac.init(key);
byte[] result1 = theMac.doFinal(plain);
if (!isMacLengthExpected(theMacAlgo, result1.length)) {
return false;
}
// Reset Mac and calculate result2
theMac.reset();
theMac.update(plain[0]);
theMac.update(plain, 1, OFFSET - 1);
byte[] result2 = theMac.doFinal(tail);
// Return result
if (!java.util.Arrays.equals(result1, result2)) {
System.out.println("result1 and result2 are not the same:");
System.out.println("result1: " + dumpByteArray(result1));
System.out.println("result2: " + dumpByteArray(result2));
return false;
} else {
System.out.println("Resulted MAC with update and doFinal is same");
}
return true;
}
/**
* Uses a random generator to initialize a message, instantiate a Mac object
* according to the given PBMAC1 algorithm, initialize the object with a
* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),
* feed the message into the Mac object all at once and get the output MAC
* as result1. Reset the Mac object, chop the message into three pieces,
* feed into the Mac object sequentially, and get the output MAC as result2.
* Finally, compare result1 and result2 and see if they are the same.
*
* @param theMacAlgo PBMAC algorithm to test
* @param thePBKDF2Algo PBKDF2 algorithm to test
* @return true - the test is passed; false - otherwise.
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
int OFFSET = 5;
// Some message for which a MAC result will be calculated
byte[] plain = new byte[25];
new SecureRandom().nextBytes(plain);
// Form tail - is one of the three pieces
byte[] tail = new byte[plain.length - OFFSET];
System.arraycopy(plain, OFFSET, tail, 0, tail.length);
// Obtain a SecretKey using PBKDF2
SecretKey key = getSecretKey(thePBKDF2Algo);
// Instantiate Mac object and init it with a SecretKey and calc result1
Mac theMac = Mac.getInstance(theMacAlgo);
theMac.init(key);
byte[] result1 = theMac.doFinal(plain);
if (!isMacLengthExpected(theMacAlgo, result1.length)) {
return false;
}
// Reset Mac and calculate result2
theMac.reset();
theMac.update(plain[0]);
theMac.update(plain, 1, OFFSET - 1);
byte[] result2 = theMac.doFinal(tail);
// Return result
if (!java.util.Arrays.equals(result1, result2)) {
System.out.println("result1 and result2 are not the same:");
System.out.println("result1: " + dumpByteArray(result1));
System.out.println("result2: " + dumpByteArray(result2));
return false;
} else {
System.out.println("Resulted MAC with update and doFinal is same");
}
return true;
}
/**
* Updates the given {@link Mac}. This generates a digest for valueToDigest and the key the Mac was initialized
*
* @param mac
* the initialized {@link Mac} to update
* @param valueToDigest
* the value to update the {@link Mac} with
* <p>
* The InputStream must not be null and will not be closed
* </p>
* @return the updated {@link Mac}
* @throws IOException
* If an I/O error occurs.
* @throws IllegalStateException
* If the Mac was not initialized
* @since 1.x
*/
public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
mac.reset();
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
mac.update(buffer, 0, read);
read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return mac;
}
/**
* Resets and then updates the given {@link Mac} with the value.
*
* @param mac
* the initialized {@link Mac} to update
* @param valueToDigest
* the value to update the {@link Mac} with
* <p>
* The InputStream must not be null and will not be closed
* </p>
* @return the updated {@link Mac}
* @throws IOException
* If an I/O error occurs.
* @throws IllegalStateException
* If the Mac was not initialized
*/
public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
mac.reset();
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
mac.update(buffer, 0, read);
read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return mac;
}
/**
* Resets and then updates the given {@link Mac} with the value.
*
* @param mac
* the initialized {@link Mac} to update
* @param valueToDigest
* the value to update the {@link Mac} with
* <p>
* The InputStream must not be null and will not be closed
* </p>
* @return the updated {@link Mac}
* @throws IOException
* If an I/O error occurs.
* @throws IllegalStateException
* If the Mac was not initialized
*/
public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
mac.reset();
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
mac.update(buffer, 0, read);
read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return mac;
}
/**
* Resets and then updates the given {@link Mac} with the value.
*
* @param mac
* the initialized {@link Mac} to update
* @param valueToDigest
* the value to update the {@link Mac} with (maybe null or empty)
* @return the updated {@link Mac}
* @throws IllegalStateException
* if the Mac was not initialized
*/
public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
mac.reset();
mac.update(valueToDigest);
return mac;
}