Giter VIP home page Giter VIP logo

subtle's People

Contributors

3for avatar alfmar avatar brycx avatar centril avatar cperezz avatar dsprenkels avatar ebfull avatar federicomenaquintero avatar hdevalence avatar isislovecruft avatar jethrogb avatar lrazovic avatar mp4096 avatar newpavlov avatar saleemrashid avatar survived avatar tarcieri avatar tonychain avatar trevor-crypto avatar trinity-1686a avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

subtle's Issues

Prusti for verified Rust crypto

Hi, has there been any interest in creating some tooling for verified crypto? I think the rust crypto community will welcome this. Prusti seems like it might be the right tool for the job, but it could leverage some extra help to ensure constant-time ops, although I am not sure if it can down to the assembly level, which Vale manages to do. I think tooling approaching what Evercrypt or something like Cryptol+C has might be nice. For additional context, here is the query I made to the project Everest team.

I also wonder what the interest of Zcash or other organisations might be in supporting such a project.

Provide a `Choice.unwrap_bool()` convenience wrapper

In code elsewhere, I keep repeating variants of the following pattern:

        match orig.ct_eq(&check).unwrap_u8() {
            0 => Err(MacError::AuthenticationError),
            1 => Ok(mac.message.clone()),
            _ => unsafe { ::core::hint::unreachable_unchecked() },
        }

It would be nice to have a convenience wrapper to do this, except rather than errors return true or false.

Implement ok_or() for CtOption<T>

Currently, working with bls12_381 we have functions like Scalar::from_bytes() which returns a CtOption.

This is fine since it's "marking" the function as a const_time fn. The problem is that the type is really unflexible since you don't have any way to transform the CtOption to Result<T, Error> appart of doing something like:

if ct_opt.is_some() {
     return ct_opt.unwrap()
} else {
    return Err(....)
}

Is there any reason why ok_or() it's not implemented for CtOption? Or any workarround to that?

Add a `CtOption` to `Option` conversion?

For now, if one wants to convert a CtOption to an Option (say, at the end of a computation, when constant-time doesn't matter anymore) they need to manually write an if ... else block.

let foo: CtOption<T> = ...
let bar: Option<T> = if foo.is_some().into() {
    foo.unwrap()
} else {
    None
};

Would it make sense to expose an unwrap_option method?

  • On the one hand, this would allow more idiomatic Rust constructs, e.g. early return with ? such as let bar: T = foo.unwrap_option()?;.
  • On the other hand, one can argue that an if ... else block is more explicit, which allows to more easily spot the variable-timeness of it.

Support for constant-time ordering comparisons?

For now, the library only supports constant-time equality comparison.

Could it be extended to support constant-time ordering comparisons (https://doc.rust-lang.org/std/cmp/trait.Ord.html)? In particular for slices of the same length (using lexicographical comparison).

One application would be private key generation for curves like P-256 using rejection sampling, where the rejection requires an ordering comparison between the generated secret and the curve order.

I'm not sure whether it would make sense to extend the Choice type to support three states, or to just expose a less-than API returning a boolean choice.

should the `black_box` asm block be marked volatile?

I remember watching many Chandler Carruth talks in my past life as a C++ developer. Chandler Carruth is a major contributor to llvm.

I found a choice moment from one of his talks (watch for about 1 min)

https://www.youtube.com/watch?v=nXaxk27zwlk&amp=&t=40m40s

"The two scariest tokens for the optimizer are asm volatile"

here's the black box function at current revision

/// This function is a best-effort attempt to prevent the compiler
/// from knowing anything about the value of the returned `u8`, other
/// than its type.
///
/// Uses inline asm when available, otherwise it's a no-op.
#[cfg(all(feature = "nightly", not(any(target_arch = "asmjs", target_arch = "wasm32"))))]
#[inline(always)]
fn black_box(mut input: u8) -> u8 {
    debug_assert!((input == 0u8) | (input == 1u8));

    // Move value through assembler, which is opaque to the compiler, even though we don't do anything.
    unsafe { asm!("" : "=r"(input) : "0"(input) ) }

    input
}

I suspect that the asm block should actually have the volatile token here for llvm to see.

Moreover, I think that this code comment:

    // Move value through assembler, which is opaque to the compiler, even though we don't do anything.

is not correct -- the compiler CAN pull out your inline assembly and start optimizing it, UNLESS you mark it volatile. This is based largely on my understanding of Chandler Carruth's talks, and informal discussions with my boss at my previous job who had earlier been a core developer of clang and a major contributor to llvm.

Note that, I am not an expert on compilers or llvm, and I'm not claiming to be one, but I wonder if you would be interested in a patch to make this like:

    unsafe { asm!("" : "=r"(input) : "0"(input) : : "volatile" ) }

or if you know a good reason not to do this, cause then I would learn something :)

Why does ConditionallySelectable require Copy?

I'm working on an embedded versions of ed25519, and considering whether to use your library, or roll my own. I'd like to have more control over what is copied.

On the one hand, I think ConditionallySelectable could use Clone as trait bound, and then later in the provided method conditional_swap explicitly clone (instead of the implict copy in the derefence). AFAIK, Copy types would always implement Clone in the same way, so this would strictly extend applicability of the trait. If you agree, I can PR this, it's just two changed lines.

On the other hand, the implementation I am currently using, which is a transliteration of the TweetNaCl code, does not use any copy or clone at all:

type Limbs = [i64; 16];

#[derive(Clone,Debug,Default)]
pub struct FieldElement(pub Limbs);

pub fn conditional_swap(p: &mut FieldElement, q: &mut FieldElement, b: i64) {
    let mask: i64 = !(b - 1);
    for (pi, qi) in p.0.iter_mut().zip(q.0.iter_mut()) {
        let t = mask & (*pi ^ *qi);
        *pi ^= t;
        *qi ^= t;
    }
}

Therefore, I'm not sure I agree with deriving conditional swap from select. What is the rationale here, besides minimal implementation cost?

EDIT: I see you overwrite the provided implementation for integral types, so I guess the idea is for users to do so as well for their own types?

doesnt compile on stable 1.25.0

not sure if it's supposed to compile on non nighly:

error[E0554]: #![feature] may not be used on the stable release channel
  --> /home/aep/.cargo/registry/src/github.com-1ecc6299db9ec823/subtle-0.3.0/src/lib.rs:20:34
   |
20 | #![cfg_attr(feature = "nightly", feature(i128_type))]
   |                                  ^^^^^^^^^^^^^^^^^^^

Nightly building issue

When I build with the latest nightly now I get the following error

error: the legacy LLVM-style asm! syntax is no longer supported
   --> /home/vsts/.cargo/registry/src/github.com-1ecc6299db9ec823/subtle-2.2.2/src/lib.rs:150:14
    |
150 |     unsafe { asm!("" : "=r"(input) : "0"(input) ) }
    |              ----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |              |
    |              help: replace with: `llvm_asm!`
    |
    = note: consider migrating to the new asm! syntax specified in RFC 2873
    = note: alternatively, switch to llvm_asm! to keep your code working as it is

Not sure why I get this in 2.2.3 either. Is this the right place to put this?

Short-circuit in debug mode resulting in non-constant-time execution

I have been testing subtle using dudect, provided by dudect-bencher.

From what I can tell, there is a short-circuit in both black_box functions and the From<Choice> for bool trait implementation for Choice. This affects both stable and nightly, but in debug-mode only.

I have only tested ct_eq.

The asserts that seem to short-circuit are:

debug_assert!(source.0 == 0u8 || source.0 == 1u8);

debug_assert!(input == 0u8 || input == 1u8);

debug_assert!(input == 0u8 || input == 1u8);

Commit bf3888e changes the debug_assert OR to a strict evaluation.

Before applying commit bf3888e in #42, these were the t-tests that dudect-bencher reported

  • nightly + debug:
running 1 bench
bench test_secure_cmp seeded with [0xc8437c3f, 0x1ebd6d87, 0x4143a2d8, 0xd9e40fe5]
bench test_secure_cmp ... : n == +0.334M, max t = +747.27294, max tau = +1.29251, (5/tau)^2 = 14
  • nightly + release:
running 1 bench
bench test_secure_cmp seeded with [0xdd26324, 0xb0cd6929, 0x38345f3b, 0xe33981da]
bench test_secure_cmp ... : n == +0.861M, max t = -2.28511, max tau = -0.00246, (5/tau)^2 = 4121111
  • stable + debug:
running 1 bench
bench test_secure_cmp seeded with [0x8de2c6f6, 0xef48ef86, 0x1331bfd1, 0x6318f891]
bench test_secure_cmp ... : n == +0.663M, max t = +955.01525, max tau = +1.17311, (5/tau)^2 = 18
  • stable + release:
bench test_secure_cmp seeded with [0x88de063f, 0xa3944eaa, 0xa16ddc08, 0x4860f51b]
bench test_secure_cmp ... : n == +0.997M, max t = -1.68096, max tau = -0.00168, (5/tau)^2 = 8821035

After applying commit bf3888e:

  • nightly + debug:
running 1 bench
bench test_secure_cmp seeded with [0xf66c77e4, 0xb6ad3111, 0x3fc3413b, 0x957ba0f4]
bench test_secure_cmp ... : n == +0.997M, max t = +1.55842, max tau = +0.00156, (5/tau)^2 = 10261010
  • nightly + release:
running 1 bench
bench test_secure_cmp seeded with [0x1a77a729, 0x7de4a2f2, 0x55470f7a, 0xa4a18553]
bench test_secure_cmp ... : n == +0.247M, max t = -1.39785, max tau = -0.00281, (5/tau)^2 = 3155259
  • stable + debug:
running 1 bench
bench test_secure_cmp seeded with [0x47063cc9, 0x66d3dc0e, 0x20ece803, 0xad3363ae]
bench test_secure_cmp ... : n == +0.994M, max t = +2.07018, max tau = +0.00208, (5/tau)^2 = 5796406
  • stable + release:
running 1 bench
bench test_secure_cmp seeded with [0x8587213f, 0xfb937a4f, 0xaab1fee2, 0x88f71c10]
bench test_secure_cmp ... : n == +0.983M, max t = +2.50388, max tau = +0.00253, (5/tau)^2 = 3919187

The tests can be found here: https://github.com/brycx/orion-dudect/tree/subtle-short-circuit/ct-bencher.

Remove TravisCI and add github worker

Travis is broken and hasn't been running in about a year. They claim they support open source projects, but they've told me for the past year that I need to buy credits from them for $69 (not nice) per month. :(

CI failing due to xargo tooling issues

The CI is failing due to xargo tooling for ARM builds; I'm not sure how to fix it, so I'm going to remove it temporarily, if someone wants to reconfigure it and add it back they're welcome to do so.

Outdated code in https://doc.dalek.rs/src/ ?

When looking at https://doc.dalek.rs/src/subtle/lib.rs.html (linked from the "docs" badge in the README), the code seems quite outdated compared to the GitHub repository. For example, the implementation of ct_eq computes the and of all the bits, which was changed 4 months ago to a shorter & more efficient implementation in 92451be.

The version referenced in the Cargo.toml snippet at https://doc.dalek.rs/subtle/ is also 2.1 whereas there has already been multiple 2.2.x versions.

On the contrary, https://docs.rs/subtle/ generated by https://crates.io/crates/subtle is always pointing to the latest version of the library. Does it make sense to duplicate documentation in https://doc.dalek.rs/ given that docs.rs is automatically up-to-date? It's especially confusing that the "documentation" link in the header of the crates.io page differs from the "docs badge" link.

Alternative license

I am working on a project that has a policy to avoid BSD 2- and 3-clause licenses due to the complexity of satisfying the attribution clause:

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Would you consider dual-licensing this project? Eg with MIT and/or Apache 2.0 licenses?

`1.0.0-pre.0` release

After checking that the API we have is the one we want, we should publish a 1.0.0-pre.0 release.

How to check for "less than"?

I am trying to implement check for <=, but as far as I can tell I can only check for equality with this crate. Is this something that could be added here?

derive macros to extend constant-time comparisons to user-defined aggregate structs

TODO

Problem

As described in #98, the Signal client crypto implementation wants to use subtle to filter and sort PrivateKey structs with constant-time operations, but goes through a hacky two-step process to achieve this by first serializing the PrivateKey struct to a byte slice (which often incurs a heap allocation for legacy reasons with the Signal code), then calling the .ct_eq() implementation predefined for byte slices. #98 proposes a method with a lookup table to process Ordering-like results without branching.

Solution

I'm not deeply familiar with the problem space of constant-time operations, but I saw that someone else had already worked out how to accumulate sequences of constant-time logical operations in that .ct_eq() implementation for byte slices, so in #99 I exposed the IteratedOperation trait and related structs for specific iterated logical comparisons.

Result

I created a proc macro crate at https://github.com/cosmicexplorer/subtle-derive. Example doctest from that crate:

 use subtle::ConstantTimeOrd;
 use subtle_derive::{ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, ConstEq, ConstPartialOrd, ConstOrd};

 #[derive(Debug, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess, ConstEq, ConstPartialOrd, ConstOrd)]
 pub struct S(pub u8);
 impl ConstantTimeOrd for S {}

 assert!(S(0) == S(0));
 assert!(S(0) < S(1));
 assert!(S(0) <= S(1));

If the current maintainers think it fits, I could instead convert my subtle-derive crate into a PR against this repo instead (and we could hide the proc macro dependency behind a "derive" feature flag the way serde does: https://serde.rs/derive.html).

Choice: invariant not upheld in release mode

From taking a look at the documentation the Choice type is meant to be a wrapper around a 0u8 or a 1u8. This invariant is upheld while running in debug mode (since debug_asserts are used) but isn't upheld when running in release mode.
This simple example illustrates the behavior:

fn main() {
    let c: Choice = 3u8.into();
    println!("{:?}", c);
}
> cargo run
thread 'main' panicked at 'assertion failed: (input == 0u8) | (input == 1u8)'
> cargo run --release
Choice(3)

Constant-time Option<T>

Currently, when taking a variable-time function that returns Option<T> and making it constant-time, you need to return (Choice, T) and then require that the caller checks the Choice before using the result. It would be safer to wrap this as CTOption<T>(Choice, T), and then provide equivalent is_none(), is_some() functions that check the Choice, and an unwrap() function that panics if the Choice is false.

This could also possibly provide CTOption<T>::ct_map(), by computing the map function over the internal T regardless of the value of Choice (with the result still being restricted by the API).

Use predication intrinsics (i.e. CMOV) for `ConditionallySelectable`

The foundation of ConditionallySelectable is bitwise masking of values + XOR, using the input Choice to generate a conditional mask, such that the mask erases one of the two values from the XOR output:

https://github.com/dalek-cryptography/subtle/blob/b4b070c/src/lib.rs#L477-L503

This seems fine for now (and is the best thing possible in a portable implementation), but may have issues with future LLVM versions which are able to deduce how to rewrite such code with a branch.

CPUs provide predication intrinsics such as x86's conditional move (a.k.a. CMOV) family of instructions. Intel has guaranteed that the CMOV family operates in constant time on all extant Intel CPUs. ARM provides conditional select (a.k.a. CSEL) instructions which perform a similar function.

Within the @RustCrypto project, we've made a cmov crate which provides a portable abstraction for this based on the now stable inline assembly support added to Rust 1.59: https://github.com/RustCrypto/utils/tree/master/cmov

...however its implementation is simple and could be copied into subtle to avoid a dependency.

Clarify assembly review

subtle/src/lib.rs

Lines 332 to 338 in 6b6a81a

// This loop shouldn't be shortcircuitable, since the compiler
// shouldn't be able to reason about the value of the `u8`
// unwrapped from the `ct_eq` result.
let mut x = 1u8;
for (ai, bi) in self.iter().zip(_rhs.iter()) {
x &= ai.ct_eq(bi).unwrap_u8();
}

Doesn't really rule out a simple if x == 0 goto end optimization. I assume the assembly was inspected but that should probably be annotated because it would have to be repeated when the compiler does smarter things.

arrays_equal

Current implementation

pub fn arrays_equal(a: &[u8], b: &[u8]) -> Mask {
    assert_eq!(a.len(), b.len());

    let mut x: u8 = 0;

    for i in 0 .. a.len() {
        x |= a[i] ^ b[i];
    }
    bytes_equal(x, 0)
}

Compiler might optimize the for loop like so without changing the non-CT program's behavior:

    for i in 0 .. a.len() {
        x |= a[i] ^ b[i];
        if x == !0 {
             break;
        }
    }

Ensuring `no_std` for subtle

Hello,

first of all, I am not sure if this is a bug or something that results from my bad understanding of rusts no_std environments, so please bear with me.
If I understand it correctly subtle is meant to work in no_std envs. If not, this issue can be closed.

Problem Description
I have subtle as a transitive dependency in my project, namely from the schnorrkel crate that I use. When I am compiling my project I get the following error:

  Blocking waiting for file lock on package cache
     Compiling sp-io v4.0.0-dev (https://github.com/centrifuge/substrate?branch=master#32b0fa55)
  error[E0152]: found duplicate lang item `panic_impl`
      --> /Users/frederik/.cargo/git/checkouts/substrate-c08550cb428dbcc9/32b0fa5/primitives/io/src/lib.rs:1424:1
       |
  1424 | pub fn panic(info: &core::panic::PanicInfo) -> ! {
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
       = note: the lang item is first defined in crate `std` (which `subtle` depends on)
       = note: first definition in `std` loaded from /Users/frederik/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-unknown/lib/libstd-17199824ef310338.rlib
       = note: second definition in the local crate (`sp_io`)

  error[E0152]: found duplicate lang item `oom`
      --> /Users/frederik/.cargo/git/checkouts/substrate-c08550cb428dbcc9/32b0fa5/primitives/io/src/lib.rs:1435:1
       |
  1435 | pub fn oom(_: core::alloc::Layout) -> ! {
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
       = note: the lang item is first defined in crate `std` (which `subtle` depends on)
       = note: first definition in `std` loaded from /Users/frederik/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-unknown/lib/libstd-17199824ef310338.rlib
       = note: second definition in the local crate (`sp_io`)

  For more information about this error, try `rustc --explain E0152`.
  error: could not compile `sp-io` due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
error: build failed

This error led me to the conclusion that subtle for some reason integrates rusts std lib.

Can you help me out, if this could be the case? So far my research only showed me that rust's compiler is not able to detect no_std incompatibilities in dependencies here. Although, I am not aware if this is still the case.

Thank you in advance for your help!

Rename Equal trait to ConstantTimeEq

Several users have expressed that they dislike that the trait name Equal doesn't tell you how it's supposed to differ to Eq. Originally in subtle, it was called CTEq, and many other things were prefixed with CT, and I argued that because it was coming from subtle, it should already be understood to be constant time. However, this doesn't really help someone unfamiliar with crypto implementations when they're reading some higher level code with understanding why a type might have both an Eq and an Equal implementation.

I propose naming it ConstantTimeEq, since "CT" doesn't really help people who aren't as familiar with crypto code. (Even some of my coworkers didn't know what "CT" meant when I said it in IRC at one point, and that's kind of the target audience for crypto code readability/understandability.)

Tiny bug in test

Works but should probably be x.

subtle/tests/mod.rs

Lines 61 to 62 in 6b6a81a

assert_eq!(<$t>::conditional_select(&x, &y, 0.into()), 0);
assert_eq!(<$t>::conditional_select(&x, &y, 1.into()), y);

Why does this library reference u8?

The asymmetry between unwrap_u8 and From<u8> for Choice bothers my OCD.

Similarly, the statement "[Choice] (...) is a wrapper around a u8, which should have the value either 1 (true) or 0 (false)" together with the debug_assertions on this.

Finally, there is some vagueness about the compiler "seeing through" wrapped bools, which I'd wager is equivalent to its power to see through wrapped u8s.

And given that all primitive integral types can be converted to bool via x != 0, I'd like to suggest removing u8 completely from the public API, including the unwrap_u8 method, and replacing with paired From<bool> for Choice and From<Choice> for bool.

Thoughts?

Implement `ConditionallySelectable` for `[T; N]`?

This kind of implementation seems fairly natural for big-int libraries (for example curve25519-dalek essentially does this for the specific type [u64; 5]). Now that min-const-generics are stabilized, it would nice to have a general implementation of this.

I am imagining a straightforward generalization of the curve25519-dalek technique:

impl<const N: usize> ConditionallySelectable for [T; N] where T : Copy + Default {
fn conditional_select(
    a: &[T; N],
    b: &[T; N],
    choice: Choice,
) -> [T; N] {
    let mut output = [T::default(); N];
    for i in 0..N {
        output[i] = T::conditionally_selectable(&a[i], &b[i], choice);
    }
    output
}

I don't know if the trait bound I give for T is precisely what is required though. It's not fully clear to me currently why ConditionallySelectable requires T to be Copy.

For my particular use case, I have a simple wrapper type around a [u64; N] that is not Copy (I want to write some constant-time bigint arithmetic that minimizes stack allocations. As a theorist who is trying to learn Rust I have no clue how actually useful this is, but it is the project I chose). If the above was implemented for [T; N], I could implement ConditionallySelectable. It could also potentially replace the code in curve25519-dalek, but as you probably want the loop unrolled that might not be worth it (although hopefully the compiler would unroll it of course).

Switch to `hint::black_box` when it becomes available

Tracking issue: rust-lang/rfcs#2360

Previous suggestions for black_box (like volatile read/write) wouldn't work, because we want to be able to use Choices in hot loops, and adding overhead makes that harder. However, the proposed hint::black_box should work for us and will let us have timing protections on stable Rust (if/when it's stabilized).

Combine multiple `CtOption`al results

My problem

struct C(A, B);

fn create_c(a: &[u8], b: &[u8]) -> CtOption<C> {
    let a: CtOption<A> = A::from_bytes(a);
    let b: CtOption<B> = B::from_bytes(b);
    // ???
}

Proposed solution

impl<T,U> CtOption<T> {
    pub fn merge<U>(self, other: CtOption<U>) -> CtOption<(T,U)> {
        CtOption {
            value: (self.value, other.value),
            is_some: self.is_some & other.is_some,
        }
    }
}
let c = a.merge(b).map(|(a, b)| C(a,b));

May I prepare a PR? Or do you have any better idea?

Exposing constant-time `is_zero`?

Given that the ct_eq implementations are currently implemented as an is_zero under the hood (by xor-ing the compared values), would it make sense to expose an ct_is_zero method in the ConstantTimeEq trait? Some implementations could then derive ct_eq from ct_is_zero.

If one needs to check whether a value is zero, it should be more efficient to do directly with an ct_is_zero method rather than constructing a temporary zero value for the purpose of comparing it.

Subtle2.3.0 cannot be compiled on my machine

This error occurred when I try to complile blake2 on Termux on my Android device:
IMG_20201102_213331
I think there is nothing wrong with my device because I can compile other crates successfully, maybe this is a bug?

packaging: privacy-breach-generic

I'm packaging subtle for debian and the .deb got flagged with these warnings:

W: librust-subtle-dev: description-too-long
W: librust-subtle-dev: privacy-breach-generic usr/share/cargo/registry/subtle-0.9.0/docs/assets/rustdoc-include-katex-header.html [<link rel="stylesheet" href="https://doc.dalek.rs/assets/katex/katex.min.css">] (https://doc.dalek.rs/assets/katex/katex.min.css)
W: librust-subtle-dev: privacy-breach-generic usr/share/cargo/registry/subtle-0.9.0/docs/assets/rustdoc-include-katex-header.html [<script src="https://doc.dalek.rs/assets/katex/katex.min.js">] (https://doc.dalek.rs/assets/katex/katex.min.js)
W: librust-subtle-dev: privacy-breach-generic usr/share/cargo/registry/subtle-0.9.0/docs/assets/rustdoc-include-katex-header.html [<script src="https://doc.dalek.rs/assets/katex/contrib/auto-render.min.js">] (https://doc.dalek.rs/assets/katex/contrib/auto-render.min.js)

I'm not very familiar with the docs system, but is there a way to include those js files in the repo itself so it's not including scripts from remote origins?

Thanks!

i128 feature gate

I plan to use subtle instead of constant_time_eq in RustCrypto. But I would like to keep to support Rust 1.21 for now. So it would be nice if you'll add enabled-by-default i128 feature gate.

P.S.: CI tests for MSRV would be nice as well.

Conversions between CtOption and Option

(I believe @str4d originally suggested this)

When implementing functions that don't need to be constant time (i.e. that work on public values), but when doing so using functions which are designed to work on values that are potentially secret and therefore return CtOption, it'd be nice to be able to explicitly opt into a CtOption -> Option conversion within the non-constant-time code.

I'd suggest adding a From<CtOption<_>> for Option impl similar to the existing Choice -> bool conversion for these cases.

Should subtle provide generic impls of Conditionally{Assignable, Negatable, Swappable}?

Should subtle provide generic-impls at all? I'm trying to use subtle in a library of my own at the moment, and it's creating issues. For example, if I have the following type:

#[derive(Copy)]
pub struct Thing<T>(pub T)

Then I can impl ConditionallySelectable for it, but to impl ConditionallySwappable, I have to have my own feature generic-impls2 (different name for disambiguation) and then do:

#[cfg(not(feature = "generic-impls2"))]
impl<T: ConditionallySwappable> ConditionallySwappable for Thing<T> {
    fn conditional_swap(...) {
        self.0.conditional_swap(&mut other.0, choice);
    }
}

Now, I could impl ConditionallySwappable for Thing with an additional Copy bound on T, but that's unnecessarily restrictive and also, IMO, not correct: swapping Thing should only require the inner type to also be ConditionallySwappable.

Using the above type is thus problematic because invoking Thing::conditional_swap would involve having conditional trait bounds that depend on generic-impls2:

#[cfg(feature = "generic-impls2")]
fn do_stuff<T: ConditionallySwappable + Copy>(val: T) { 
    let something = Thing(T);
    something.conditional_swap(...);
}

#[cfg(not(feature = "generic-impls2"))]
fn do_stuff<T: ConditionalSwap>(val: T) { 
    let something = Thing(T);
    something.conditional_swap(...);
}

PS: Apologies for the burst of issues I've filed over the past couple of days!

Allow for constructing a constant Choice

Choice doesn't provide a const fn for constructing the Choice, since you must use From to construct it. It might be nice to provide a from_u8 const constructor for users that need it.

Supporting `CtOption::map` for non-`Default` types?

For now, CtOption::map requires a Default type.

This is especially problematic for types which require some constant-time validation of the input in their public constructors, say with the following API.

impl T {
    pub fn from_bytes(bytes: &[u8; N]) -> CtOption<T> { ... }
}

In that case, exposing a Default for T would allow the caller to bypass from_bytes validation by creating a Default.

Could there be a variant of map with an explicitly provided dummy value? Same question for CtOption::and_then.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.