b |= bytes1[startPos1] ^ bytes2[startPos2]; return equalsConstantTime(b, 0);
b |= bytes1[startPos1] ^ bytes2[startPos2]; return equalsConstantTime(b, 0);
b |= bytes1[startPos1] ^ bytes2[startPos2]; return equalsConstantTime(b, 0);
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1.length() != s2.length()) { return 0; } // Benchmarking demonstrates that using an int to accumulate is faster than other data types. int c = 0; for (int i = 0; i < s1.length(); ++i) { c |= s1.charAt(i) ^ s2.charAt(i); } return equalsConstantTime(c, 0); } }
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1.length() != s2.length()) { return 0; } // Benchmarking demonstrates that using an int to accumulate is faster than other data types. int c = 0; for (int i = 0; i < s1.length(); ++i) { c |= s1.charAt(i) ^ s2.charAt(i); } return equalsConstantTime(c, 0); } }
return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 3) ^ UNSAFE.getInt(bytes2, baseOffset2 + 3)) | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 6: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 2) ^ UNSAFE.getInt(bytes2, baseOffset2 + 2)) | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 5: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 1) ^ UNSAFE.getInt(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 4: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1) ^ UNSAFE.getInt(bytes2, baseOffset2)), 0); case 3: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 2: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 1: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); default: return ConstantTimeUtils.equalsConstantTime(result, 0);
return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 3) ^ UNSAFE.getInt(bytes2, baseOffset2 + 3)) | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 6: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 2) ^ UNSAFE.getInt(bytes2, baseOffset2 + 2)) | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 5: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 1) ^ UNSAFE.getInt(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 4: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1) ^ UNSAFE.getInt(bytes2, baseOffset2)), 0); case 3: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 2: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 1: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); default: return ConstantTimeUtils.equalsConstantTime(result, 0);
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1.length() != s2.length()) { return 0; } // Benchmarking demonstrates that using an int to accumulate is faster than other data types. int c = 0; for (int i = 0; i < s1.length(); ++i) { c |= s1.charAt(i) ^ s2.charAt(i); } return equalsConstantTime(c, 0); } }
return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 3) ^ UNSAFE.getInt(bytes2, baseOffset2 + 3)) | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 6: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 2) ^ UNSAFE.getInt(bytes2, baseOffset2 + 2)) | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 5: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 1) ^ UNSAFE.getInt(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 4: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1) ^ UNSAFE.getInt(bytes2, baseOffset2)), 0); case 3: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 2: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 1: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); default: return ConstantTimeUtils.equalsConstantTime(result, 0);
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1 instanceof AsciiString && s2 instanceof AsciiString) { if (s1.length() != s2.length()) { return 0; } AsciiString s1Ascii = (AsciiString) s1; AsciiString s2Ascii = (AsciiString) s2; return PlatformDependent.equalsConstantTime(s1Ascii.array(), s1Ascii.arrayOffset(), s2Ascii.array(), s2Ascii.arrayOffset(), s1.length()); } return ConstantTimeUtils.equalsConstantTime(s1, s2); }
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }
b |= bytes1[startPos1] ^ bytes2[startPos2]; return equalsConstantTime(b, 0);
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1.length() != s2.length()) { return 0; } // Benchmarking demonstrates that using an int to accumulate is faster than other data types. int c = 0; for (int i = 0; i < s1.length(); ++i) { c |= s1.charAt(i) ^ s2.charAt(i); } return equalsConstantTime(c, 0); } }
return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 3) ^ UNSAFE.getInt(bytes2, baseOffset2 + 3)) | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 6: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 2) ^ UNSAFE.getInt(bytes2, baseOffset2 + 2)) | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 5: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1 + 1) ^ UNSAFE.getInt(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 4: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getInt(bytes1, baseOffset1) ^ UNSAFE.getInt(bytes2, baseOffset2)), 0); case 3: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1 + 1) ^ UNSAFE.getChar(bytes2, baseOffset2 + 1)) | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); case 2: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getChar(bytes1, baseOffset1) ^ UNSAFE.getChar(bytes2, baseOffset2)), 0); case 1: return ConstantTimeUtils.equalsConstantTime(result | (UNSAFE.getByte(bytes1, baseOffset1) ^ UNSAFE.getByte(bytes2, baseOffset2)), 0); default: return ConstantTimeUtils.equalsConstantTime(result, 0);
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }
/** * Compare two {@link CharSequence} objects without leaking timing information. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * String s1 = "foo"; * String s2 = "foo"; * String s3 = "foo"; * String s4 = "goo"; * boolean equals = (equalsConstantTime(s1, s2) & equalsConstantTime(s3, s4)) != 0; * </pre> * @param s1 the first value. * @param s2 the second value. * @return {@code 0} if not equal. {@code 1} if equal. */ static int equalsConstantTime(CharSequence s1, CharSequence s2) { if (s1 instanceof AsciiString && s2 instanceof AsciiString) { if (s1.length() != s2.length()) { return 0; } AsciiString s1Ascii = (AsciiString) s1; AsciiString s2Ascii = (AsciiString) s2; return PlatformDependent.equalsConstantTime(s1Ascii.array(), s1Ascii.arrayOffset(), s2Ascii.array(), s2Ascii.arrayOffset(), s1.length()); } return ConstantTimeUtils.equalsConstantTime(s1, s2); }
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }
/** * Compare two {@code byte} arrays for equality without leaking timing information. * For performance reasons no bounds checking on the parameters is performed. * <p> * The {@code int} return type is intentional and is designed to allow cascading of constant time operations: * <pre> * byte[] s1 = new {1, 2, 3}; * byte[] s2 = new {1, 2, 3}; * byte[] s3 = new {1, 2, 3}; * byte[] s4 = new {4, 5, 6}; * boolean equals = (equalsConstantTime(s1, 0, s2, 0, s1.length) & * equalsConstantTime(s3, 0, s4, 0, s3.length)) != 0; * </pre> * @param bytes1 the first byte array. * @param startPos1 the position (inclusive) to start comparing in {@code bytes1}. * @param bytes2 the second byte array. * @param startPos2 the position (inclusive) to start comparing in {@code bytes2}. * @param length the amount of bytes to compare. This is assumed to be validated as not going out of bounds * by the caller. * @return {@code 0} if not equal. {@code 1} if equal. */ public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) { return !hasUnsafe() || !unalignedAccess() ? ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) : PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length); }