Movatterモバイル変換


[0]ホーム

URL:


packageeqaf

  1. Overview
  2. Docs

You can search for identifiers within the package.

in-package search v0.2.0

Constant-time equal function on string

Install

Dune Dependency

Authors

Maintainers

Sources

eqaf-0.10.tbz
sha256=67d1369c57c4d2d14a10d02632d45e355224abeb98aec08979c0bae5843092ee
sha512=7f75b5d5667e3605f8d95e2d6fda40953129033e6a342ee2c98ee4135c2428e1db87547971868605ab989374757c47c21c5397d4c3da578952d716826a156979

Description

This package provides an equal function on string in constant-time to avoid timing-attack with crypto stuff.

Published:26 Jun 2024

README

Eq(af) - Constant time equal function

This library implements variousconstant time algorithms, first and foremost theEqaf.equal equality testing function forstring.

While the test suite has a number of external dependencies, the library itself does not have any dependencies besides the OCaml standard library. This should makeeqaf small, self-contained, and easy to integrate in your code.

The "constant time" provided by this library isconstant in the sense that the time required to execute the functions does not depend on thevalues of the operands. The purpose is to help programmer shield their code from timing-based side-channel attacks where an adversary tries to measure execution time to learn about the contents of the operands. They arenot necessarily "constant time" in the sense that each invocation takes exactly the same amount of microseconds.

Constant time implementations are beneficial in many different applications; cryptographic libraries likedigestif, but also practial code that deal with sensitive information (like passwords) benefit from constant time execution in select situations. A practical example of where this matters is theLucky Thirteen attack against the TLS protocol, where a short-circuiting comparison compromised the message encryption layer in many vulnerable implementations.

You can generate and view the documentation in a browser with:

dune build @docxdg-open ./_build/default/_doc/_html/index.html

Contents

We found that we often had to duplicate the constant timeequal function, and to avoid replication of code and ensure maintainability of the implementation, we decided to provide a little package which implements theequal function onstring. Since then, we have added a number of other useful constant time implementations:

  • compare_be andcompare_le: can be used to compare integers (or actual strings) of any size in either big-endian or little-endian representation. Regular string comparison (e.g.String.compare) is usuallyshort-circuiting, which results in an adversary being able to learn the contents of compared strings by timing repeated executions. If the lengths do not match, the semantics forcompare_be follow those ofString.compare, andcompare_le those ofString.compare (reverse str).

    • Thecompare_be_with_len andcompare_le_with_len are similar, but does a constant time comparison of the lengths of the two strings and the~len parameter. If the lengths do not match, an exception is thrown (which leaks the fact that the lengths did not match, but not the lengths or the contents of the input operands).

  • exists_uint8 : ?off -> f:(int -> bool) -> string -> bool: implements the equivalent ofList.exists onstring, but executing in constant time with respect to the contents of the string and?off. The user provides a callback function that is given each byte as an integer, and is responsible for ensuring this function also operates in constant time.

  • find_uint8: similar toexists_uint8, but implementing the functionality ofList.find: It returns the string index of the first match.

  • divmod: constant time division and modulo operations. The execution time of both operations in normal implementations are notoriously dependent on the operands. Theeqaf implementation uses an algorithm ported fromSUPERCOP.

  • ascii_of_int32 : digits:int -> int32 -> string: Turns theint32 argument into a fixed-width (of length= digits) left-padded string containing the decimal representation, ex:ascii_of_int32 ~digits:4 123l is"0123". Usually programming languages provide similar functionality (ex:Int32.to_string), but are vulnerable to timing attacks since they rely on division. This implementation is similar, but usesEqaf.divmod to mitigate side channels.

  • lowercase_ascii anduppercase_ascii implement functionality equivalent to the identically named functions inStdlib.String module, but without introducing a timing side channel.

  • hex_of_string: constant-time hex encoding. Normally hex encoding is implemented with either a table lookup or processor branches, both of which introduce side channels for an adversary to learn about the contents of the string being encoded. That can be a problem if an adversary can repeatedly trigger encoding of sensitive values in your application and measure the response time.

  • string_of_hex: constant-time hex decoding. Inverse ofhex_of_string, but with support for decoding uppercase and lowercase letters alike.

This package, ifcstruct orbase-bigarray is available, will make thisequal function for them too (aseqaf.cstruct andeqaf.bigarray).

A number of low-level primitives used byEqaf are also exposed to enable you to construct your own constant time implementations:

  • zero_if_not_zero : int -> int:(if n <> 0 then 0 else 1), or!n in the C programming language.

  • one_if_not_zero : int -> int:(if n <> 0 then 1 else 0), or!!n in the C programming language.

    • bool_of_int : int -> bool, likeone_if_not_zero but cast tobool

    • int_of_bool : bool -> int, inverse ofbool_of_int

  • select_int : int -> int -> int -> int:select_int choose_b a b is a constant time utility for branching, but always executing all the branches (to ensure constant time operation):

    let select_int choose_b a b = if choose_b = 0 then a else b
  • select_a_if_in_range : ~low:int -> ~high:int -> n:int -> int -> int -> int Similar toselect_int, but checking for inclusion in a range rather than testing for zero - a CT version of:

    let select_a_if_in_range ~low ~high ~n a b =  if low <= n && n <= high  then a  else b

Check tool

To ensure correctness,eqaf ships with a test suite to measure the functions and comparing results both to theStdlib implementations and to executions of the same function with similar length/size input. The goal is to try to spot implementation weaknesses that rely on thevalues of the function operands.

The check tool will first attempt to calculate how many executions are required to get statistically sound numbers (sorting out random jitter from external factors like other programs executing on the computer).

Then, using linear regression, we compare the results and verify that we did not spot differences: the regression coefficient should be close to0.0.

You can testeqaf with this:

$ dune exec check/check.exe

Q/A

Q How to updateeqaf implementation?

Aeqaf is fragile where the most important assumption is times needed to computeequal. Soeqaf provides thecheck tool but results from it can be disturb by side-channel (like hypervisor). In a bare-metal environment,check strictly works and should return0.

Qeqaf is slower thanString.compare, it's possible to optimize it?

A The final goal ofeqaf is to provide asafe equal function. Speed is clearly not what we want where we prefer to provide an implementation which does not leak informations like: where is the first byte which differs betweena andb.

Q Which attackeqaf prevents?

Aeqaf provide an equal function to avoid a timing attack. Most of equal or compare functions (likeString.compare) leave at the first byte which differs. A possible attack is to see how long we need to compare two values, like an user input and a password.

Logically, the longer this time is, the more user input is the password. So when we need to compare sensible values (like hashes), we should use something likeeqaf. The distribution provides an example of this attack:

$ dune exec attack/attack.exeRandom: [|218;243;59;121;8;57;151;218;212;91;181;41;|].471cd8bc03992a31f8f0f0c55e9e477d471cd8bc03992a31f8f0f0c55e9e477d

The first value is the hash, the second is what we found just by an introspection of time needed by ourequal function.

Qeqaf provides only equal function onstring?

A The first implementation usestring, then, we copy/paste the code withbigarray and provide it only ifbase-bigarray is available. Finally, we provide anequal function forcstruct only if this package is available.

So, it's not only aboutstring but for some others data-structures.

Q Why we need to do a linear regression to check assumptions oneqaf?

A As we said, times are noisy by several side-computation (hypervisor, kernel, butterfly...). So, if we record two times how long we spend to computeequal, we will have 2 different values - close each others but different.

So we need to have a bunch of samples and do an analyze on them to get an approximation. From that, we do 2 analyzes:

  • get the approximation where we compare 2 same values

  • get the approximation where we compare 2 different values

From these results, we need to do an other analyze on these approximations to see if they are close each others or not. In the case ofeqaf, it should be the case (and if it is, that meanseqaf does not leak a time information according inputs). In the case ofString.compare, we should have a big difference - and confirm expected behaviors.

Dependencies (2)

  1. dune>= "2.0"
  2. ocaml>= "4.07.0"

Dev Dependencies (5)

  1. bechamelwith-test
  2. fmtwith-test & >= "0.8.7"
  3. crowbarwith-test
  4. alcotestwith-test
  5. base64with-test & >= "3.0.0"

Conflicts

None


[8]ページ先頭

©2009-2025 Movatter.jp