profile
viewpoint
Emil Lundberg emlun @Yubico Stockholm, Sweden https://emlun.se Engineer, physicist, tinkerer.

emlun/adventofcode-2019 5

My solutions to Advent of Code 2019

emlun/factorio-grus 3

GRand Unified Storage system

emlun/gws2 3

Colorful KISS helper for git workspaces

emlun/gradle-autowrap 2

Gradle Wrapper wrapper gradle

emlun/arducoopter 1

Summer project at KTH, the Royal Institute of Technology, Sweden. The goal is to find a way for quadrotors to cooperatively perform missions they cannot do alone. The hardware used is quadrotors from DIY Drones. The repository is a fork from ArduPilot Mega.

emlun/bob 1

Backward Output Brainfuck

emlun/btsync-autoconfig 1

Automatically create btsync config file skeletons for users when necessary (unmaintained since I don't use btsync anymore)

emlun/FScience 1

FrozenPepper's FScience Science Transfer Plugin for Kerbal Space Program

emlun/how-to-load-styles-from-npm-modules-using-webpack 1

How to load styles from NPM modules using Webpack

emlun/adventofcode-2016-clojure 0

Advent of Code 2016 as Clojure practice

Pull request review commentashpil/rush

Implement alias/unalias builtin

+use assert_cmd::assert::IntoOutputPredicate;+use assert_cmd::cmd::Command;+use escargot::CargoBuild;+use predicates_core::Predicate;++fn test_io<I, O, P>(+    input: I,+    output: O,+) -> Result<assert_cmd::assert::Assert, Box<dyn std::error::Error>>+where+    I: Into<Vec<u8>>,+    O: IntoOutputPredicate<P>,+    P: Predicate<[u8]>,+{+    let mut cmd = Command::from_std(+        CargoBuild::new()+            .bin(env!("CARGO_PKG_NAME"))+            .release()+            .run()?+            .command(),+    );+    let assert = cmd.write_stdin(input).assert();+    Ok(assert.stdout(output))+}++#[test]+fn alias_defines_and_prints_aliases() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "alias foo=echo+foo bar+alias+alias foo+alias boo='far' foo boo+alias+",+        "$> $> bar+$> alias foo='echo'+$> alias foo='echo'+$> alias foo='echo'+alias boo='far'+$> alias boo='far'+alias foo='echo'+$> +",+    )?+    .success()+    .code(0);+    Ok(())+}++#[test]+fn aliases_do_not_self_recurse() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "alias echo='echo foo'+echo bar+",+        "$> $> foo bar+$> +",+    )?+    .success()+    .code(0);+    Ok(())+}++#[test]+fn aliases_can_be_nested() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "alias foo='bar asdf && bar fdsa'+alias bar=echo+foo boo+",+        "$> $> $> asdf+fdsa boo+$> +",+    )?+    .success()+    .code(0);+    Ok(())+}++#[test]+fn echo_prints_argument() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "echo foo",+        "$> foo+$> +",+    )?+    .success()+    .code(0);+    Ok(())+}++#[test]+fn empty_input_prints_newline() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "", "$> +",+    )?+    .success()+    .code(0);+    Ok(())+}++#[test]+fn exit_prints_nothing() -> Result<(), Box<dyn std::error::Error>> {+    test_io("exit", "$> ")?.success().code(0);+    Ok(())+}++#[test]+fn unalias_removes_alias() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "alias foo='echo' bar='oche'+alias+unalias foo+alias+unalias bar+foo foo+",+        "$> $> alias bar='oche'+alias foo='echo'+$> $> alias bar='oche'+$> $> $> +",+    )?+    .stderr(+        "rush: foo: No such file or directory (os error 2)+",+    )+    .success()+    .code(0);+    Ok(())+}++#[test]+fn unalias_dash_a_removes_all_aliases() -> Result<(), Box<dyn std::error::Error>> {+    test_io(+        "alias foo='echo' bar='oche'+alias+unalias -a+alias+alias foo='echo' bar='oche'+alias+unalias -a asdf+alias+",+        "$> $> alias bar='oche'+alias foo='echo'+$> $> $> $> alias bar='oche'

As far as I can tell, the shell isn't printing newlines unless the command does (by using println! instead of print!, for example). In interactive mode, most newlines are entered by the user rather than printed by the shell.

emlun

comment created time in a day

PullRequestReviewEvent

pull request commentashpil/rush

Implement alias/unalias builtin

Thanks for the review! I'll try to fix these things up in the next couple of days.

emlun

comment created time in a day

push eventemlun/time-rs

Emil Lundberg

commit sha 52d2008a6eb55650315480951f60179cc9c2ce09

Use explicit enum type instead of Self alias For compatibility with Rust 1.36

view details

Emil Lundberg

commit sha 7e262c042ad0880108f4cb63b50443cd53ce481a

Use max_value() instead of MAX For compatibility with Rust 1.36

view details

push time in 2 days

push eventemlun/time-rs

Emil Lundberg

commit sha 3f56e6d03191fcddfdf04856840d416d7e514165

Fix clippy lint

view details

push time in 2 days

push eventemlun/time-rs

Emil Lundberg

commit sha 5758961a74843a8a30c3abc85e09a943f6640d6e

cargo +nightly fmt

view details

Emil Lundberg

commit sha 7de63a07de269a1e22f797d9a91507210a57d2d7

Break long lines in macros

view details

push time in 3 days

PR opened time-rs/time

Implement quickcheck::Arbitrary for data types

Alright, here's a go at #286. This adds a quickcheck-gen feature (it can't be just quickcheck because it also needs to enable rand - unless you require the user to also enable rand explicitly) and a subcrate time-quickcheck-tests that tests that feature.

I've intentionally left Instant out since it seems like values of that type aren't intrinsically meaningful on their own. It also seems quite easy to obtain an Instant from a Duration if needed, and that type does get an Arbitrary implementation.

+579 -1

0 comment

7 changed files

pr created time in 3 days

push eventemlun/time-rs

Emil Lundberg

commit sha 1281e26a1366a4b7a6a4cf2a3a7f9becdccffa2c

Implement quickcheck::Arbitrary for Date

view details

Emil Lundberg

commit sha 2bb9c3a279bd1aeb35cf24032fd82d4986597d2d

Implement quickcheck::Arbitrary for Duration

view details

Emil Lundberg

commit sha ba632dcdff8e652936946e9edaa3f3553eb3d3e0

Extract macro test_generator_size

view details

Emil Lundberg

commit sha 19acda80c275abe76a9fb572c4e53fcb879801ae

Extract macro test_shrink

view details

Emil Lundberg

commit sha 22b9935662424ab0595a94fb3d11d1db655a2fb0

Implement quickcheck::Arbitrary for Time

view details

Emil Lundberg

commit sha 59142d692d246a31c37d16c0f4ff403888fca848

Use explicit cmp instead of <= in macro Seems like Emacs gets confused by the < character otherwise.

view details

Emil Lundberg

commit sha b86d27c8fb3fde1ab652effcc1e3d9f08c2ac5dd

Implement quickcheck::Arbitrary for PrimitiveDateTime

view details

Emil Lundberg

commit sha ed3bb3933935f0a8983fe15454444970344ebc1b

Implement quickcheck::Arbitrary for UtcOffset

view details

Emil Lundberg

commit sha 84e31518baddbad11cb53d3af05074c538537729

Implement quickcheck::Arbitrary for OffsetDateTime

view details

Emil Lundberg

commit sha bc43ce270a53502e2d48d94e2d0670045267cf3e

Add optional minimum value to macro test_generator_size

view details

Emil Lundberg

commit sha adefde0f6ad79f33fcee679a64e96f06db5474fe

Implement quickcheck::Arbitrary for Weekday

view details

Emil Lundberg

commit sha e1b690399118f208f2ce8c1b23a7c101291f871b

Add doc comments about quickcheck-gen feature

view details

push time in 3 days

create barnchemlun/time-rs

branch : quickcheck

created branch time in 3 days

pull request commentashpil/rush

Implement alias/unalias builtin

@ashpil Have you had time to look at this?

emlun

comment created time in 3 days

issue commentYubico/java-webauthn-server

Authenticator extensions {credProtect} are not a subset of requested extensions {}

Oh, wait, I'd forgotten - there is the allowUnrequestedExtensions setting on RelyingParty. It's disabled by default, but we should probably change it to be enabled by default. Anyway, try enabling it, that should fix your problem.

mttcr

comment created time in 4 days

issue commentrzwitserloot/lombok

[BUG] Regression? @Builder.ObtainVia with different type broke in 1.18.12

Oh, and for completeness, a workaround: remove @Builder.ObtainVia and add a builder method overload that takes the nullable plain type. The builder method can be private if you don't want a nullable type in the public API. One could also argue this is just a better solution than using @Builder.ObtainVia in the first place.

emlun

comment created time in 5 days

issue openedrzwitserloot/lombok

[BUG] Regression? @Builder.ObtainVia with different type broke in 1.18.12

Describe the bug

In Lombok 1.18.10, a method used for @Builder.ObtainVia can return a different type than the one declared for the field, as long as there is builder method accepting the relevant type. This is no longer supported in Lombok 1.18.12 due to a refactorization of the generated code. This was useful for example for value types with private nullable fields with a non-nullable Optional getter.

To Reproduce

Minimal example:

package org.example;

import java.util.Optional;
import lombok.Builder;
import lombok.NonNull;

@Builder(toBuilder = true)
public class LombokObtainViaOtherType {

  @Builder.ObtainVia(method = "getFoo")
  private final String foo;

  public Optional<String> getFoo() {
    return Optional.ofNullable(foo);
  }

  public static class LombokObtainViaOtherTypeBuilder {
    LombokObtainViaOtherTypeBuilder foo(@NonNull Optional<String> foo) {
      this.foo = foo.orElse(null);
      return this;
    }
  }
}

In Lombok 1.18.12 and later, this code fails with the error:

LombokObtainViaOtherType.java:5: error: incompatible types: Optional<String> cannot be converted to String

Delombok shows why. Lombok 1.18.10 produces:

  @java.lang.SuppressWarnings("all")
  @lombok.Generated
  public LombokObtainViaOtherTypeBuilder toBuilder() {
    return new LombokObtainViaOtherTypeBuilder().foo(this.getFoo());
  }

while Lombok 1.18.12 produces:

  @java.lang.SuppressWarnings("all")
  @lombok.Generated
  public LombokObtainViaOtherType.LombokObtainViaOtherTypeBuilder toBuilder() {
    final String foo = this.getFoo();
    return new LombokObtainViaOtherType.LombokObtainViaOtherTypeBuilder().foo(foo);
  }

So Lombok 1.18.12 and later assumes that the @Builder.ObtainVia method returns the field's declared type, while Lombok 1.18.10 and earlier only assume that there exists some builder method that accepts the returned type.

Expected behavior I expected my code to keep working after a Lombok upgrade, but perhaps this is an unintended "feature" that only worked by accident. Either way I figured I'd report it since the change broke some code, but I half-expect this is a wontfix.

Version info (please complete the following information):

  • Lombok version: 1.18.12 or later
  • Platform: javac 11.0.8

Additional context

The real-world example that exposed this was, among other similar cases in the same project, this timeout member and its associated builder method.

created time in 5 days

pull request commentemlun/adventofcode-2019

Speedup day12 by a factor of 2 using symmetry

Sorry, I wanted to verify the reasoning but haven't gotten around to it yet. I'll see if I can do it soon but I can't promise anything. Don't worry about the clippy errors, I'll fix those.

TheThirdOne

comment created time in 5 days

issue commentYubico/java-webauthn-server

Authenticator extensions {credProtect} are not a subset of requested extensions {}

Ah, right. This is intended behaviour that has become a bug because of changes in the WebAuthn spec. In level 1, step 12 of §7.1. Registering a New Credential reads (emphasis added):

  1. Verify that the values of the client extension outputs in clientExtensionResults and the authenticator extension outputs in the extensions in authData are as expected, considering the client extension input values that were given as the extensions option in the create() call. In particular, any extension identifier values in the clientExtensionResults and the extensions in authData MUST be also be present as extension identifier values in the extensions member of options, i.e., no extensions are present that were not requested. In the general case, the meaning of "are as expected" is specific to the Relying Party and which extensions are in use.

In level 2 (which is still a work in progress), precisely because of the new credProtect extension, the requirement to reject unsolicited extensions has been removed:

  1. Verify that the values of the client extension outputs in clientExtensionResults and the authenticator extension outputs in the extensions in authData are as expected, considering the client extension input values that were given in options.extensions and any specific policy of the Relying Party regarding unsolicited extensions, i.e., those that were not specified as part of options.extensions. In the general case, the meaning of "are as expected" is specific to the Relying Party and which extensions are in use.

This will require a rather simple update of the library to fix, but I'm afraid there's nothing you can do as a library user to work around it.

mttcr

comment created time in 5 days

issue commentw3c/webauthn

Inconsistent display formats for OIDs

Will fix after PR #1491 is merged.

emlun

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentw3c/webauthn

Mention Intersection Observer v2 in sec considerations

 The main benefits offered to [=[WRPS]=] by this specification include: 1. The [=[RP]=] does not need to store additional secrets in order to gain the above benefits.  As stated in the [[#sctn-conforming-relying-parties|Conformance]] section, the [=[RP]=] MUST behave as described in [[#sctn-rp-operations]]-to obtain all of the above security benefits. However, one notable use case that departs slightly from this is described in the-next section.+to obtain all of the above security benefits. However, one notable use case that departs slightly from this is described below in [[#sctn-attestation-limitations]].+++### Visibility Considerations for Embedded Usage ### {#sctn-seccons-visibility}++Simplistic use of WebAuthn in an embedded context, e.g., within <{iframe}>s as described in [[#sctn-iframe-guidance]], may make users vulnerable to <dfn>UI Redressing</dfn> attacks, also known as "[Clickjacking](https://en.wikipedia.org/wiki/Clickjacking)". This is where an attacker overlays their own UI on top of a [=[RP]=]'s intended UI and attempts to trick the user into performing unintended actions with the [=[RP]=]. For example, using these techniques, an attacker might be able to trick users into purchasing items, transferring money, etc.++Therefore, it is important for an [=[RP]=] having embedded WebAuthn-wielding content to ensure that their content's UI is visible to the user. An emerging means to do so is by observing the status of the experimental [Intersection Observer v2](https://w3c.github.io/IntersectionObserver/v2/)'s `isVisible` attribute. For example, the [=[RPS]=] script running in the embedded context could pre-emptively load itself in a popup window if it detects `isVisble` being set to `false`, thus side-stepping any occluding of their content that may be occuring over the embedded content.

I think the [=[RPS]=] alias is for the plural, right?

Therefore, it is important for an [=[RP]=] having embedded WebAuthn-wielding content to ensure that their content's UI is visible to the user. An emerging means to do so is by observing the status of the experimental [Intersection Observer v2](https://w3c.github.io/IntersectionObserver/v2/)'s `isVisible` attribute. For example, the [=[RP]=]'s script running in the embedded context could pre-emptively load itself in a popup window if it detects `isVisble` being set to `false`, thus side-stepping any occluding of their content that may be occuring over the embedded content.
equalsJeffH

comment created time in 6 days

PullRequestReviewEvent

Pull request review commentw3c/webauthn

Adding Apple Anonymous Attestation Statement Format

 if the [=authenticator=] does not support [=attestation=]. : Verification procedure :: Return implementation-specific values representing [=attestation type=] [=None=] and an empty [=attestation trust path=]. +## Apple Anonymous Attestation Statement Format ## {#sctn-apple-anonymous-attestation}++This attestation statement format is exclusively used by Apple for certain types of Apple devices that support WebAuthn.++: Attestation statement format identifier+:: apple++: Attestation types supported+:: [=Anonymization CA=]++: Syntax+:: The syntax of an Apple attestation statement is defined as follows:++    ```+    $$attStmtType //= (+                          fmt: "apple",+                          attStmt: appleStmtFormat+                      )++    appleStmtFormat = {+                          x5c: [ credCert: bytes, * (caCert: bytes) ]+                      }+    ```++    The semantics of the above fields are as follows:++    : x5c+    :: |credCert| followed by its certificate chain, each encoded in X.509 format.++    : credCert+    :: The credential public key certificate used for attestation, encoded in X.509 format.++: Signing procedure+::+    1. Let |authenticatorData| denote the authenticator data for the attestation, and let |clientDataHash| denote the [=hash of the serialized client data=].+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Let Apple anonymous attestation CA generate an X.509 certificate for the [=credential public key=] and include the |nonce| as a certificate extension with OID ( 1.2.840.113635.100.8.2 ). |credCert| denotes this certificate. The |credCert| thus serves as a proof of the attestation, and the included |nonce| proves the attestation is live. In addition to that, the |nonce| also protects the integrity of the |authenticatorData| and [=client data=].

From 2020-10-21: no such name is defined at this time.

alanwaketan

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent

issue openedw3c/webauthn

Inconsistent display formats for OIDs

The spec currently displays X.509 OIDs in at least three different ways, and after PR #1491 there will be four:

We should standardize on one display format. I propose we use "code quotes" like this for both the OID and, if available, its name:

- If |attestnCert| contains an extension with OID `1.3.6.1.4.1.45724.1.1.4` (`id-fido-gen-ce-aaguid`) verify [...]

created time in 6 days

Pull request review commentw3c/webauthn

Adding Apple Anonymous Attestation Statement Format

 if the [=authenticator=] does not support [=attestation=]. : Verification procedure :: Return implementation-specific values representing [=attestation type=] [=None=] and an empty [=attestation trust path=]. +## Apple Anonymous Attestation Statement Format ## {#sctn-apple-anonymous-attestation}++This attestation statement format is exclusively used by Apple for certain types of Apple devices that support WebAuthn.++: Attestation statement format identifier+:: apple++: Attestation types supported+:: [=Anonymization CA=]++: Syntax+:: The syntax of an Apple attestation statement is defined as follows:++    ```+    $$attStmtType //= (+                          fmt: "apple",+                          attStmt: appleStmtFormat+                      )++    appleStmtFormat = {+                          x5c: [ credCert: bytes, * (caCert: bytes) ]+                      }+    ```++    The semantics of the above fields are as follows:++    : x5c+    :: |credCert| followed by its certificate chain, each encoded in X.509 format.++    : credCert+    :: The credential public key certificate used for attestation, encoded in X.509 format.++: Signing procedure+::+    1. Let |authenticatorData| denote the authenticator data for the attestation, and let |clientDataHash| denote the [=hash of the serialized client data=].+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Let Apple anonymous attestation CA generate an X.509 certificate for the [=credential public key=] and include the |nonce| as a certificate extension with OID ( 1.2.840.113635.100.8.2 ). |credCert| denotes this certificate. The |credCert| thus serves as a proof of the attestation, and the included |nonce| proves the attestation is live. In addition to that, the |nonce| also protects the integrity of the |authenticatorData| and [=client data=].+    5. Set |x5c| to |credCert| followed by its certificate chain.++: Verification procedure+:: Given the verification procedure inputs |attStmt|, |authenticatorData| and |clientDataHash|, the verification procedure is as follows:+    1. Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the contained fields.+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Verify |nonce| matches the value of the extension with OID ( 1.2.840.113635.100.8.2 ) in |credCert|.+    5. Verify credential public key matches the Subject Public Key of |credCert|.

Same here, and we can also link the "credential public key" term.

    5. Verify that the [=credential public key=] equals the Subject Public Key of |credCert|.
alanwaketan

comment created time in 6 days

Pull request review commentw3c/webauthn

Adding Apple Anonymous Attestation Statement Format

 if the [=authenticator=] does not support [=attestation=]. : Verification procedure :: Return implementation-specific values representing [=attestation type=] [=None=] and an empty [=attestation trust path=]. +## Apple Anonymous Attestation Statement Format ## {#sctn-apple-anonymous-attestation}++This attestation statement format is exclusively used by Apple for certain types of Apple devices that support WebAuthn.++: Attestation statement format identifier+:: apple++: Attestation types supported+:: [=Anonymization CA=]++: Syntax+:: The syntax of an Apple attestation statement is defined as follows:++    ```+    $$attStmtType //= (+                          fmt: "apple",+                          attStmt: appleStmtFormat+                      )++    appleStmtFormat = {+                          x5c: [ credCert: bytes, * (caCert: bytes) ]+                      }+    ```++    The semantics of the above fields are as follows:++    : x5c+    :: |credCert| followed by its certificate chain, each encoded in X.509 format.++    : credCert+    :: The credential public key certificate used for attestation, encoded in X.509 format.++: Signing procedure+::+    1. Let |authenticatorData| denote the authenticator data for the attestation, and let |clientDataHash| denote the [=hash of the serialized client data=].+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Let Apple anonymous attestation CA generate an X.509 certificate for the [=credential public key=] and include the |nonce| as a certificate extension with OID ( 1.2.840.113635.100.8.2 ). |credCert| denotes this certificate. The |credCert| thus serves as a proof of the attestation, and the included |nonce| proves the attestation is live. In addition to that, the |nonce| also protects the integrity of the |authenticatorData| and [=client data=].

Is there a name for this OID? (Like "OID 1.3.6.1.4.1.45724.1.1.4 (id-fido-gen-ce-aaguid)" in §8.2.1. Packed Attestation Statement Certificate Requirements)

alanwaketan

comment created time in 6 days

Pull request review commentw3c/webauthn

Adding Apple Anonymous Attestation Statement Format

 if the [=authenticator=] does not support [=attestation=]. : Verification procedure :: Return implementation-specific values representing [=attestation type=] [=None=] and an empty [=attestation trust path=]. +## Apple Anonymous Attestation Statement Format ## {#sctn-apple-anonymous-attestation}++This attestation statement format is exclusively used by Apple for certain types of Apple devices that support WebAuthn.++: Attestation statement format identifier+:: apple++: Attestation types supported+:: [=Anonymization CA=]++: Syntax+:: The syntax of an Apple attestation statement is defined as follows:++    ```+    $$attStmtType //= (+                          fmt: "apple",+                          attStmt: appleStmtFormat+                      )++    appleStmtFormat = {+                          x5c: [ credCert: bytes, * (caCert: bytes) ]+                      }+    ```++    The semantics of the above fields are as follows:++    : x5c+    :: |credCert| followed by its certificate chain, each encoded in X.509 format.++    : credCert+    :: The credential public key certificate used for attestation, encoded in X.509 format.++: Signing procedure+::+    1. Let |authenticatorData| denote the authenticator data for the attestation, and let |clientDataHash| denote the [=hash of the serialized client data=].+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Let Apple anonymous attestation CA generate an X.509 certificate for the [=credential public key=] and include the |nonce| as a certificate extension with OID ( 1.2.840.113635.100.8.2 ). |credCert| denotes this certificate. The |credCert| thus serves as a proof of the attestation, and the included |nonce| proves the attestation is live. In addition to that, the |nonce| also protects the integrity of the |authenticatorData| and [=client data=].+    5. Set |x5c| to |credCert| followed by its certificate chain.++: Verification procedure+:: Given the verification procedure inputs |attStmt|, |authenticatorData| and |clientDataHash|, the verification procedure is as follows:+    1. Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the contained fields.+    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.+    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.+    4. Verify |nonce| matches the value of the extension with OID ( 1.2.840.113635.100.8.2 ) in |credCert|.

"Matches" could imply some looser comparison like a pattern or prefix match, so I would say "equals" here for clarity (assuming that is what is meant).

    4. Verify that |nonce| equals the value of the extension with OID ( 1.2.840.113635.100.8.2 ) in |credCert|.
alanwaketan

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentw3c/webauthn

Abstracting the concept of Privacy CA/Attestation CA into Anonymization CA

 calling {{CredentialsContainer/create()|navigator.credentials.create()}} they se     Note: This concept typically leads to multiple attestation certificates. The attestation certificate requested most recently         is called "active". -    Note: [=Attestation statements=] conveying [=attestations=] of [=attestation type|type=] [=AttCA=] use the same data structure-    as [=attestation statements=] conveying [=attestations=] of [=attestation type|type=] [=Basic=], so the two attestation types-    are, in general, distinguishable only with externally provided knowledge regarding the contents of the [=attestation-    certificates=] conveyed in the [=attestation statement=].+: <dfn>Anonymization CA</dfn> (<dfn>AnonCA</dfn>)+:: In this case, the [=authenticator=] works with a cloud-operated [=Anonymization CA=] owned by its manufacturer to dynamically generate per-[=credential=] [=attestation certificates=] on the CA such that no identification information of the [=authenticator=] will be revealed to [=[RPS]=] in the [=attestation statement=].++    Note: [=Attestation statements=] conveying [=attestations=] of [=attestation type|type=] [=AttCA=] or [=AnonCA=] use the same data structure+        as [=attestation statements=] conveying [=attestations=] of [=attestation type|type=] [=Basic=], so the three attestation types

Minor suggestion, feel free to ignore:

        as those of [=attestation type|type=] [=Basic=], so the three attestation types
alanwaketan

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

delete branch Yubico/developers.yubico.com

delete branch : new-aaguids

delete time in 7 days

pull request commentYubico/developers.yubico.com

Add new YubiKey AAGUIDs to yubico-metadata.json

Superseded by #334

emlun

comment created time in 7 days

create barnchYubico/developers.yubico.com

branch : update-u2f-metadata

created branch time in 7 days

pull request commenttime-rs/time

Add benchmarks

Mostly runtime panics, like if an Err.unwrap() or zero division would sneak in somehow. But given Rust's baseline safety, not a whole lot I suppose.

emlun

comment created time in 8 days

pull request commenttime-rs/time

Add benchmarks

Thank you too!

One last thing, regarding the last commit: you might also want to run cargo test --benches in CI. That'll compile and test-run all the benchmarks but without taking measurements, so it runs very fast.

emlun

comment created time in 8 days

delete branch emlun/time-rs

delete branch : benchmarks

delete time in 8 days

issue closedYubico/java-webauthn-server

Can not deserialize com.yubico.webauthn.RegisteredCredential with jackson

I want to store CredentialRegistration of each user in database. Serializer is working as expected. I serialize that with this code which works fine:

Collection<CredentialRegistration> registrations = ....;
JacksonCodecs.json().writeValueAsString(registrations)

It stores something like this:

[
    {
        "signatureCount": 0,
        "credential": {
            "credentialId": "Qh5671PvhA_YYyUE1rZ_oh45e2KiHXm7uQj6MthdfHj3D3DoHNNy1IEBbw7eDLhSRaf440gYeU-mW9xauPAXww",
            "userHandle": "lA_444PjkzZWA2PiTafgdfsuty2jKv44wedfgev8tPc",
            "publicKeyCose": "pQMmAQIsdfv-tZ3fkpkfsdfsdfsdfdfsdf36dgpTVqKiUAxIhjgvbn8jWv9bdsdfsdfsdfc_fND3WGvbnbvnzRpL3U",
            "signatureCount": 0
        },
        "userIdentity": {
            "name": "1",
            "displayName": "admin",
            "id": "lA_gWtPwerbnnvbnvbnrhtryhwetgefg2jvbnbn7ev8tPc"
        },
        "credentialNickname": "default",
        "username": "1",
        "registrationTime": "2020-03-14T23:15:51.444Z"
    }
]

Deserialization error

But when I attempt to deserialize it back, using code bellow:

JacksonCodecs.json().readValue(temp, new TypeReference<Collection<CredentialRegistration>>(){});

It produces this error:

Cannot construct instance of com.yubico.webauthn.RegisteredCredential (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

RegisteredCredential class is annotated using lombok but why jackson can not deserialize it? Is there a workaround?

closed time in 8 days

salehdeh76

issue commentYubico/java-webauthn-server

Can not deserialize com.yubico.webauthn.RegisteredCredential with jackson

The fix is now released in version 1.7.0. Thanks for your feedback!

salehdeh76

comment created time in 8 days

issue closedYubico/java-webauthn-server

Support for Face/TouchID on iOS14 - Safari

Hi,

I have a fido2-server built on this library (and this is great!), and I would like to know if there is a plan to support the apple attestation format in the next versions, or how to handle it. Here is the error I get when trying to use Face/TouchID with my server.

Failed to resolve attestation type; unknown attestation statement format: apple

This error is returned here: https://github.com/Yubico/java-webauthn-server/blob/bdc1b7fa1a8c79f8250f520372f53c85070d515d/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishRegistrationSteps.java#L466

I don't have this issue when using the https://demo.yubico.com/playground, so I wonder how you did resolve this!

Thanks Jules

closed time in 8 days

DeenOub

issue commentYubico/java-webauthn-server

Support for Face/TouchID on iOS14 - Safari

The fix is now released in version 1.7.0. Thanks for the report!

DeenOub

comment created time in 8 days

issue commentYubico/java-webauthn-server

Use of EC Keys produces - Point does not match field size

@rajairside Could you provide some more information as described above?

rajairside

comment created time in 8 days

push eventYubico/java-webauthn-server

Emil Lundberg

commit sha d4c706b4ca76ada0f3e10614647694150aa29535

Disambiguate JSON deserialization of AuthenticatorTransport This broke in Jackson 2.12.0-rc1, seems like the deserializer somehow started choosing the `valueOf` function instead of the `of` function. At first this seemed like a regression in Jackson, but it was ambiguous on our side either way.

view details

Emil Lundberg

commit sha 1895c062bcbdd97cd5f637e472b23645d71fb300

Print Java version in release-verify-signatures workflow

view details

Emil Lundberg

commit sha d5c809f94fc3e2fa74c3dac72ef17a6aefad6432

Add newer YubiKey examples to tests

view details

Emil Lundberg

commit sha 2f6387b03d6e3ae4e0dd7b08c5a216d80dfc7128

Add joint AAGUID for YubiKey 5/5C NFC

view details

Emil Lundberg

commit sha 68ecba1d2640682a14966eaaa4238fd356e9a330

Change name "YubiKey 5 Series security key" to "YubiKey 5 Series" in metadata

view details

Emil Lundberg

commit sha 8293a6a95613e091a3c894a1d947bf9f2f61fece

Release 1.7.0 webauthn-server-attestation: - Updated name of AAGUID `2fc0579f811347eab116bb5a8db9202a` to "YubiKey 5/5C NFC" - Changed name of "YubiKey 5 Series security key" to "YubiKey 5 Series" webauthn-server-core: Changes: - Fixed crash on unknown attestation statement formats - Unless `RelyingParty.allowUntrustedAttestation` is set to `false`, unknown attestation statements will now pass as untrusted attestations, instead of throwing an IllegalArgumentException. - Disambiguated Jackson deserialization of class `AuthenticatorTransport` New features: - Class `RegisteredCredential` can now be serialized to and deserialized from JSON.

view details

Emil Lundberg

commit sha b25168aff384659b8ceb7f62bf949cec867692ce

Merge remote-tracking branch 'origin/master' into master

view details

push time in 8 days

created tagYubico/java-webauthn-server

tag1.7.0

Server-side Web Authentication library for Java https://www.w3.org/TR/webauthn/#rp-operations

created time in 8 days

delete branch Yubico/java-webauthn-server

delete branch : update-metadata

delete time in 8 days

create barnchYubico/java-webauthn-server

branch : update-metadata

created branch time in 9 days

push eventemlun/time-rs

Emil Lundberg

commit sha edba47dd4e10adf9a77c38458e1e844b9c34401c

Remove //s in middle of comment line

view details

push time in 9 days

Pull request review commenttime-rs/time

Add benchmarks

+/// Helper macro that wraps code blocks in benchmark functions, and makes sure+/// to add all those functions to the Criterion benchmark group.+#[macro_export]+macro_rules! setup_benchmark {+    (+        $group_prefix:literal,+        $(+            $(#[$fn_attr:meta])*+            fn $fn_name:ident ($bencher:ident : &mut Bencher)+            $code:block+        )*+    ) => {+        $(+            $(#[$fn_attr])*+            pub fn $fn_name(c: &mut criterion::Criterion) {+                c.bench_function(&format!("{}: {}", $group_prefix, stringify!($fn_name)), |$bencher| {+                    $code+                });+            }+        )*++        criterion::criterion_group! {+            name = benches;+            config = criterion::Criterion::default()++                // Set a stricter statistical significance threshold ("p-value")+                // for deciding what's an actual performance change vs. noise.+                // The more benchmarks, the lower this needs to be+                // in order to not get lots of false positives.+                .significance_level(0.0001)++                // Ignore any performance change less than this+                // (e.g., 0.05 = // 5%) as noise,

Whoops, yep.

                // (e.g., 0.05 = 5%) as noise,
emlun

comment created time in 9 days

PullRequestReviewEvent

pull request commenttime-rs/time

Add benchmarks

Great, thanks for helping get this into shape! :smile:

emlun

comment created time in 9 days

push eventemlun/time-rs

Emil Lundberg

commit sha 8c2625b585505aedf9502516e93f140435950240

Merge target/ entries in .gitignore Co-authored-by: Jacob Pratt <the.z.cuber@gmail.com>

view details

push time in 9 days

issue commenttime-rs/time

[Feature] Provide Arbitrary trait implementation(s)?

Implementing quickcheck::Arbitrary would allow users to write tests like this:

use time::Date;
use quickcheck::quickcheck;

struct DateRange {
    from: Date,
    to: Date,
}

impl DateRange {
    fn new(from: Date, to: Date) -> Result<Self, ()> {
        Ok(DateRange { from, to })
    }
}

quickcheck! {
    fn date_range_is_well_defined(from: Date, to: Date) -> bool {
        let r = DateRange::new(from, to);
        if from <= to {
            r.is_ok()
        } else {
            r.is_err()
        }
    }
}

Without it you get a trait bound error:

error[E0277]: the trait bound `time::date::Date: quickcheck::arbitrary::Arbitrary` is not satisfied
15  | / quickcheck! {
16  | |     fn date_range_is_well_defined(from: Date, to: Date) -> bool {
17  | |         let r = DateRange::new(from, to);
18  | |         if from <= to {
...   |
23  | |     }
24  | | }
    | |_^ the trait `quickcheck::arbitrary::Arbitrary` is not implemented for `time::date::Date`

and you'd have to work around it by either constructing the Dates from smaller components, or adding some wrapper around Date so you can implement Arbitrary for the wrapper type (because you can't add implementations for imported traits to imported types).

emlun

comment created time in 9 days

issue openedtime-rs/time

[Feature] Provide Arbitrary trait implementation(s)?

I've found quickcheck to be a quite useful way to write tests. How about providing Arbitrary implementations for the types in this library as an optional feature? I'll volunteer to do it. :slightly_smiling_face:

I'm not completely familiar with the Rust ecosystem on this matter, though (I've mostly done the similar thing in Scala) - it looks like there's both quickcheck's own quickcheck::arbitrary::Arbitrary trait, and a different arbitrary::Arbitrary trait in the arbitrary crate, with no apparent relation between the two. I'm not sure which would be better to implement (if not both) - the quickcheck one seems necessary for quickcheck itself, but libfuzzer uses the one from the arbitrary crate. I'm leaning towards starting with the quickcheck one since that enables more fine-grained tests than fuzzing for full-on crashes.

created time in 10 days

push eventemlun/time-rs

Emil Lundberg

commit sha 10de330fd559c9f34cc8665b784a762c089ba863

cargo +nightly fmt

view details

push time in 10 days

pull request commenttime-rs/time

Add benchmarks

Thanks for the review! I think I got everything fixed, please let me know if I missed anything.

emlun

comment created time in 10 days

Pull request review commenttime-rs/time

Add benchmarks

+/// Helper macro that wraps code blocks in benchmark functions, and makes sure+/// to add all those functions to the Criterion benchmark group.+#[macro_export]+macro_rules! setup_benchmark {+    ($group_prefix:literal,++     $($(#[$fn_attr:meta])*+       $fn_name:ident ($bencher:ident : &mut Bencher)+       $code:block+     )*) => {+        $(+            $(#[$fn_attr])*+            pub fn $fn_name(c: &mut criterion::Criterion) {+                c.bench_function(&format!("{}: {}", $group_prefix, stringify!($fn_name)), |$bencher| {+                    $code+                });+            }+        )*++        criterion::criterion_group! {+            name = benches;+            config = criterion::Criterion::default()+                .significance_level(0.0001)+                .noise_threshold(0.05)

I added some comments, does that look good?

emlun

comment created time in 10 days

PullRequestReviewEvent

push eventemlun/time-rs

Emil Lundberg

commit sha 192be9ae79dd725f0ab632f802e51681cd6b5d63

Add comments on Criterion settings

view details

Emil Lundberg

commit sha a1e58daa0442b33d92e0a1eb5fe6b360ccdc97fe

Remove standback dependency from time-benchmarks

view details

Emil Lundberg

commit sha b63e33b04dc127f7726680ae36f01cd0a516a66f

Delete unnecessary benchmark format.rs

view details

Emil Lundberg

commit sha cde364e610ef666b631727d68fb13d6c61b84ce7

Remove unnecessary duplication in to_string() benchmarks

view details

Emil Lundberg

commit sha 34111f6c83677715186bfc59cb42d33194c18584

Delete arithmetic benchmarks

view details

Emil Lundberg

commit sha 1a8488ccbd2a11ccdefdb915ed1c84a1717bff6a

Remove benchmark of statically known value

view details

Emil Lundberg

commit sha d92a439ea22358f2ea3a207ecdde29418e3a1e92

Remove benchmark of non-public API

view details

Emil Lundberg

commit sha 86f3da45f3e566288ae3b3ed8eb9988d90611ba6

Remove unnecessary parentheses

view details

Emil Lundberg

commit sha eddb96de2bc4b66d50bb809f94a6b55fb85a0248

Remove unnecessary duplication in Time sub_duration benchmarks

view details

Emil Lundberg

commit sha 3bd3eb5d92b609ff882c6ff99147c66afb7e9c74

Pull operand out of benchmark

view details

Emil Lundberg

commit sha 47e6c1103dd39d0f3b54da378bf10f5bb0e5ff39

Make benchmar assume_offset measure what it says

view details

Emil Lundberg

commit sha 01d8fb1a59aabddc2f9f093f90221ec972be9d71

Pull method calls not under benchmark out of benchmark

view details

Emil Lundberg

commit sha 1717d6a8cda6735f5eb03a5ac740d0f385738440

Simplify hash benchmark

view details

Emil Lundberg

commit sha 2f736d819b5dd54eb4ace6dcb1d451d494b58088

Remove unnecessary for loop

view details

Emil Lundberg

commit sha 55233e65f1c12379ebce143d697797862077a1aa

Drop test_ prefix from benchmark functions

view details

push time in 10 days

Pull request review commenttime-rs/time

Add benchmarks

+use bench_util::setup_benchmark;+use criterion::BatchSize;+use std::time::SystemTime;+use time::{+    ext::{NumericalDuration, NumericalStdDuration},+    Format, OffsetDateTime,+};+use time_macros::{datetime, offset};++setup_benchmark! {+    "OffsetDateTime",++    now_utc(b: &mut Bencher) {+        b.iter(|| OffsetDateTime::now_utc());+    }++    now_local(b: &mut Bencher) {+        b.iter(||OffsetDateTime::now_local());+    }++    to_offset(b: &mut Bencher) {+        let utc = datetime!("2000-01-01 0:00 UTC");+        let offset = offset!("-1");+        let sydney = datetime!("2000-01-01 0:00").assume_offset(offset!("+11"));+        let new_york_offset = offset!("-5");+        let los_angeles_offset = offset!("-8");++        b.iter(|| (+            utc.to_offset(offset),+            sydney.to_offset(new_york_offset),+            sydney.to_offset(los_angeles_offset),+        ));+    }++    unix_epoch(b: &mut Bencher) {+        b.iter(|| OffsetDateTime::unix_epoch());+    }++    from_unix_timestamp(b: &mut Bencher) {+        b.iter(|| (+            OffsetDateTime::from_unix_timestamp(0),+            OffsetDateTime::from_unix_timestamp(1_546_300_800),+        ));+    }++    from_unix_timestamp_nanos(b: &mut Bencher) {+        b.iter(|| (+            OffsetDateTime::from_unix_timestamp_nanos(0),+            OffsetDateTime::from_unix_timestamp_nanos(1_546_300_800_000_000_000),+        ));+    }++    offset(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00");+        let plus_one_offset = offset!("+1");++        ben.iter(|| (+            a.offset(),+            b.assume_offset(plus_one_offset).offset(),+            a.to_offset(plus_one_offset).offset(),+        ));+    }++    unix_timestamp(ben: &mut Bencher) {+        let a = OffsetDateTime::unix_epoch();+        let b = OffsetDateTime::unix_epoch().to_offset(offset!("+1"));+        let c = datetime!("1970-01-01 0:00").assume_offset(offset!("-1"));+        ben.iter(|| (+            a.unix_timestamp(),+            b.unix_timestamp(),+            c.unix_timestamp(),+        ));+    }++    unix_timestamp_nanos(ben: &mut Bencher) {+        let a = datetime!("1970-01-01 0:00 UTC");+        let b = datetime!("1970-01-01 1:00 UTC").to_offset(offset!("-1"));+        ben.iter(|| (+            a.unix_timestamp_nanos(),+            b.unix_timestamp_nanos(),+        ));+    }++    date(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00 UTC").to_offset(offset!("-1"));+        ben.iter(|| (a.date(), b.date()));+    }++    time(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00 UTC").to_offset(offset!("-1"));+        ben.iter(|| (a.time(), b.time()));+    }++    year(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-12-31 23:00 UTC").to_offset(offset!("+1"));+        let c = datetime!("2020-01-01 0:00 UTC");+        ben.iter(|| (+            a.year(),+            b.year(),+            c.year(),+        ));+    }++    month(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-12-31 23:00 UTC").to_offset(offset!("+1"));+        ben.iter(|| (a.month(), b.month()));+    }++    day(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-12-31 23:00 UTC").to_offset(offset!("+1"));+        ben.iter(|| (a.day(), b.day()));+    }++    month_day(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-12-31 23:00 UTC").to_offset(offset!("+1"));+        ben.iter(|| (a.month_day(), b.month_day()));+    }++    ordinal(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-12-31 23:00 UTC").to_offset(offset!("+1"));+        ben.iter(|| (a.ordinal(), b.ordinal()));+    }++    iso_year_week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-10-04 0:00 UTC");+        let c = datetime!("2020-01-01 0:00 UTC");+        let d = datetime!("2020-12-31 0:00 UTC");+        let e = datetime!("2021-01-01 0:00 UTC");+        ben.iter(|| (+            a.iso_year_week(),+            b.iso_year_week(),+            c.iso_year_week(),+            d.iso_year_week(),+            e.iso_year_week(),+        ));+    }++    week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2020-01-01 0:00 UTC");+        let c = datetime!("2020-12-31 0:00 UTC");+        let d = datetime!("2021-01-01 0:00 UTC");+        ben.iter(|| (+            a.week(),+            b.week(),+            c.week(),+            d.week(),+        ));+    }++    weekday(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-02-01 0:00 UTC");+        let c = datetime!("2019-03-01 0:00 UTC");+        ben.iter(|| (+            a.weekday(),+            b.weekday(),+            c.weekday(),+        ));+    }++    hour(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59 UTC").to_offset(offset!("-2"));+        ben.iter(|| (a.hour(), b.hour()));+    }++    minute(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59 UTC").to_offset(offset!("+0:30"));+        ben.iter(|| (a.minute(), b.minute()));+    }++    second(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59 UTC").to_offset(offset!("+0:00:30"));+        ben.iter(|| (a.second(), b.second()));+    }++    millisecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59.999 UTC");+        ben.iter(|| (+            a.millisecond(),+            b.millisecond(),+        ));+    }++    microsecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59.999_999 UTC");+        ben.iter(|| (+            a.microsecond(),+            b.microsecond(),+        ));+    }++    nanosecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 23:59:59.999_999_999 UTC");+        ben.iter(|| (+            a.nanosecond(),+            b.nanosecond(),+        ));+    }++    format(ben: &mut Bencher) {+        let a = datetime!("2019-01-02 0:00 UTC");+        let b = datetime!("2019-01-02 3:04:05.678_901_234").assume_offset(offset!("+6:07"));+        ben.iter(|| (+            a.format("%F %r %z"),+            b.format(Format::Rfc3339),+        ));+    }++    parse(b: &mut Bencher) {+        b.iter(|| (+            OffsetDateTime::parse("2019-01-02 00:00:00 +0000", "%F %T %z"),+            OffsetDateTime::parse("2019-002 23:59:59 +0000", "%Y-%j %T %z"),+            OffsetDateTime::parse("2019-W01-3 12:00:00 pm +0000", "%G-W%V-%u %r %z"),+            OffsetDateTime::parse("2019-01-02 03:04:05 +0600", "%F %T %z"),+            OffsetDateTime::parse("2020-09-08T08:44:31+02:30", Format::Rfc3339),+            OffsetDateTime::parse("2019-01-02T03:04:05.678901234+05:06", Format::Rfc3339),+            OffsetDateTime::parse("2019-01-02T03:04:05.678901234Z", Format::Rfc3339),+            OffsetDateTime::parse("2019-01-02T03:04:05/", Format::Rfc3339),+            OffsetDateTime::parse("2019-01-02T03:04:05", Format::Rfc3339),+            OffsetDateTime::parse("2019-01-02T03:04:05.", Format::Rfc3339),+        ));+    }++    partial_eq(ben: &mut Bencher) {+        let a = datetime!("2000-01-01 0:00 UTC").to_offset(offset!("-1"));+        let b = datetime!("2000-01-01 0:00 UTC");+        ben.iter(|| a == b);+    }++    partial_ord(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00 UTC").to_offset(offset!("-1"));+        ben.iter(|| a.partial_cmp(&b));+    }++    ord(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00 UTC").to_offset(offset!("-1"));+        let c = datetime!("2019-01-01 0:00:00.000_000_001 UTC");+        ben.iter(|| (a == b, c > a));+    }++    hash(ben: &mut Bencher) {+        use std::collections::hash_map::DefaultHasher;+        use std::hash::{Hash, Hasher};++        let a = datetime!("2019-01-01 0:00 UTC");+        let b = datetime!("2019-01-01 0:00 UTC").to_offset(offset!("-1"));+        let c = datetime!("2019-01-01 0:00");++        ben.iter(|| (+            {+                let mut hasher = DefaultHasher::new();+                a.hash(&mut hasher);+                hasher.finish()

Hm, yeah, I guess so. I was thinking this checks the whole hashing procedure from start to finish, but I guess only the hash() call is really relevant to the performance of hashing this type specifically. That means we can even reuse the same Hasher instance between iteration loops.

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

+use bench_util::setup_benchmark;+use criterion::BatchSize;+use time::{+    ext::{NumericalDuration, NumericalStdDuration},+    PrimitiveDateTime,+};+use time_macros::{date, datetime, offset, time};++setup_benchmark! {+    "PrimitiveDateTime",++    new(ben: &mut Bencher) {+        let d = date!("2019-01-01");+        let t = time!("0:00");+        ben.iter(|| PrimitiveDateTime::new(d, t));+    }++    date(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        ben.iter(|| a.date());+    }++    time(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        ben.iter(|| a.time());+    }++    year(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-12-31 0:00");+        let c = datetime!("2020-01-01 0:00");+        ben.iter(|| (+            a.year(),+            b.year(),+            c.year(),+        ));+    }++    month(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-12-31 0:00");+        ben.iter(|| (a.month(), b.month()));+    }++    day(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-12-31 0:00");+        ben.iter(|| (a.day(), b.day()));+    }++    month_day(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-12-31 0:00");+        ben.iter(|| (+            a.month_day(),+            b.month_day(),+        ));+    }++    ordinal(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-12-31 0:00");+        ben.iter(|| (+            a.ordinal(),+            b.ordinal(),+        ));+    }++    iso_year_week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-10-04 0:00");+        let c = datetime!("2020-01-01 0:00");+        let d = datetime!("2020-12-31 0:00");+        let e = datetime!("2021-01-01 0:00");+        ben.iter(|| (+            a.iso_year_week(),+            b.iso_year_week(),+            c.iso_year_week(),+            d.iso_year_week(),+            e.iso_year_week(),+        ));+    }++    week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-10-04 0:00");+        let c = datetime!("2020-01-01 0:00");+        let d = datetime!("2020-12-31 0:00");+        let e = datetime!("2021-01-01 0:00");+        ben.iter(|| (+            a.week(),+            b.week(),+            c.week(),+            d.week(),+            e.week(),+        ));+    }++    sunday_based_week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2020-01-01 0:00");+        let c = datetime!("2020-12-31 0:00");+        let d = datetime!("2021-01-01 0:00");+        ben.iter(|| (+            a.sunday_based_week(),+            b.sunday_based_week(),+            c.sunday_based_week(),+            d.sunday_based_week(),+        ));+    }++    monday_based_week(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2020-01-01 0:00");+        let c = datetime!("2020-12-31 0:00");+        let d = datetime!("2021-01-01 0:00");+        ben.iter(|| (+            a.monday_based_week(),+            b.monday_based_week(),+            c.monday_based_week(),+            d.monday_based_week(),+        ));+    }++    weekday(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-02-01 0:00");+        let c = datetime!("2019-03-01 0:00");+        let d = datetime!("2019-04-01 0:00");+        let e = datetime!("2019-05-01 0:00");+        let f = datetime!("2019-06-01 0:00");+        let g = datetime!("2019-07-01 0:00");+        let h = datetime!("2019-08-01 0:00");+        let i = datetime!("2019-09-01 0:00");+        let j = datetime!("2019-10-01 0:00");+        let k = datetime!("2019-11-01 0:00");+        let l = datetime!("2019-12-01 0:00");++        ben.iter(|| (+            a.weekday(),+            b.weekday(),+            c.weekday(),+            d.weekday(),+            e.weekday(),+            f.weekday(),+            g.weekday(),+            h.weekday(),+            i.weekday(),+            j.weekday(),+            k.weekday(),+            l.weekday(),+        ));+    }++    hour(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59");+        ben.iter(|| (+            a.hour(),+            b.hour(),+        ));+    }++    minute(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59");+        ben.iter(|| (+            a.minute(),+            b.minute(),+        ));+    }++    second(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59");+        ben.iter(|| (+            a.second(),+            b.second(),+        ));+    }++    millisecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59.999");+        ben.iter(|| (+            a.millisecond(),+            b.millisecond(),+        ));+    }++    microsecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59.999_999");+        ben.iter(|| (+            a.microsecond(),+            b.microsecond(),+        ));+    }++    nanosecond(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00");+        let b = datetime!("2019-01-01 23:59:59.999_999_999");+        ben.iter(|| (+            a.nanosecond(),+            b.nanosecond(),+        ));+    }++    assume_offset(ben: &mut Bencher) {+        let a = datetime!("2019-01-01 0:00").assume_offset(offset!("UTC"));+        let b = datetime!("2019-01-01 0:00").assume_offset(offset!("-1"));+        ben.iter(|| (+            a.unix_timestamp(),+            b.unix_timestamp(),+        ));+    }

Yep, good catch!

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

+use bench_util::setup_benchmark;+use criterion::BatchSize;+use time::{+    ext::{NumericalDuration, NumericalStdDuration},+    Time,+};+use time_macros::time;++setup_benchmark! {+    "Time",++    from_hms_nanos_unchecked(ben: &mut Bencher) {+        ben.iter(|| Time::from_hms_nanos_unchecked(0, 1, 2, 3));+    }++    midnight(ben: &mut Bencher) {+        ben.iter(|| Time::midnight());+    }++    from_hms(ben: &mut Bencher) {+        ben.iter(|| (+            Time::from_hms(1, 2, 3),+            Time::from_hms(24, 0, 0),+            Time::from_hms(0, 60, 0),+            Time::from_hms(0, 0, 60),+        ));+    }++    from_hms_milli(ben: &mut Bencher) {+        ben.iter(|| (+            Time::from_hms_milli(1, 2, 3, 4),+            Time::from_hms_milli(24, 0, 0, 0),+            Time::from_hms_milli(0, 60, 0, 0),+            Time::from_hms_milli(0, 0, 60, 0),+            Time::from_hms_milli(0, 0, 0, 1_000),+        ));+    }++    from_hms_micro(ben: &mut Bencher) {+        ben.iter(|| (+            Time::from_hms_micro(1, 2, 3, 4),+            Time::from_hms_micro(24, 0, 0, 0),+            Time::from_hms_micro(0, 60, 0, 0),+            Time::from_hms_micro(0, 0, 60, 0),+            Time::from_hms_micro(0, 0, 0, 1_000_000),+        ));+    }++    from_hms_nano(ben: &mut Bencher) {+        ben.iter(|| (+            Time::from_hms_nano(1, 2, 3, 4),+            Time::from_hms_nano(24, 0, 0, 0),+            Time::from_hms_nano(0, 60, 0, 0),+            Time::from_hms_nano(0, 0, 60, 0),+            Time::from_hms_nano(0, 0, 0, 1_000_000_000),+        ))+    }++    hour(ben: &mut Bencher) {+        let a = Time::from_hms(0, 0, 0).unwrap();+        let b = Time::from_hms(0, 59, 59).unwrap();+        let c = Time::from_hms(23, 0, 0).unwrap();+        let d = Time::from_hms(23, 59, 59).unwrap();+        ben.iter(|| (+            a.hour(),+            b.hour(),+            c.hour(),+            d.hour(),+        ));+    }++    minute(ben: &mut Bencher) {+        let a = Time::from_hms(0, 0, 0).unwrap();+        let b = Time::from_hms(23, 0, 59).unwrap();+        let c = Time::from_hms(0, 23, 0).unwrap();+        let d = Time::from_hms(23, 23, 59).unwrap();+        ben.iter(|| (+            a.minute(),+            b.minute(),+            c.minute(),+            d.minute(),+        ));+    }++    second(ben: &mut Bencher) {+        let a = Time::from_hms(0, 0, 0).unwrap();+        let b = Time::from_hms(23, 59, 0).unwrap();+        let c = Time::from_hms(0, 0, 23).unwrap();+        let d = Time::from_hms(23, 59, 23).unwrap();+        ben.iter(|| (+            a.second(),+            b.second(),+            c.second(),+            d.second(),+        ));+    }++    millisecond(ben: &mut Bencher) {+        let a = Time::from_hms_milli(0, 0, 0, 0).unwrap();+        let b = Time::from_hms_milli(23, 59, 59, 0).unwrap();+        let c = Time::from_hms_milli(0, 0, 0, 999).unwrap();+        let d = Time::from_hms_milli(23, 59, 59, 999).unwrap();+        ben.iter(|| (+            a.millisecond(),+            b.millisecond(),+            c.millisecond(),+            d.millisecond(),+        ));+    }++    microsecond(ben: &mut Bencher) {+        let a = Time::from_hms_micro(0, 0, 0, 0).unwrap();+        let b = Time::from_hms_micro(23, 59, 59, 0).unwrap();+        let c = Time::from_hms_micro(0, 0, 0, 999_999).unwrap();+        let d = Time::from_hms_micro(23, 59, 59, 999_999).unwrap();+        ben.iter(|| (+            a.microsecond(),+            b.microsecond(),+            c.microsecond(),+            d.microsecond(),+        ));+    }++    nanosecond(ben: &mut Bencher) {+        let a = Time::from_hms_nano(0, 0, 0, 0).unwrap();+        let b = Time::from_hms_nano(23, 59, 59, 0).unwrap();+        let c = Time::from_hms_nano(0, 0, 0, 999_999_999).unwrap();+        let d = Time::from_hms_nano(23, 59, 59, 999_999_999).unwrap();+        ben.iter(|| (+            a.nanosecond(),+            b.nanosecond(),+            c.nanosecond(),+            d.nanosecond(),+        ));+    }++    format(ben: &mut Bencher) {+        let time = time!("0:01:02.345_678_901");+        let time_12h = time!("12:01:02");+        ben.iter(|| (+            time.format("%H"),+            time.format("%I"),+            time.format("%M"),+            time.format("%N"),+            time.format("%p"),+            time.format("%P"),+            time.format("%r"),+            time.format("%R"),+            time.format("%S"),+            time.format("%T"),+            time_12h.format("%p"),+            time_12h.format("%P"),+        ));+    }++    parse(ben: &mut Bencher) {+        ben.iter(|| (+            Time::parse("0:01:02.345678901 00", "%T.%N %H"),+            Time::parse("0:01:02.345678901 12", "%T.%N %I"),+            Time::parse("0:01:02.345678901 01", "%T.%N %M"),+            Time::parse("0:01:02.345678901 345678901", "%T.%N %N"),+            Time::parse("0:01:02.345678901 am", "%T.%N %p"),+            Time::parse("0:01:02.345678901 AM", "%T.%N %P"),+            Time::parse("0:01:02.345678901 12:01:02 am", "%T.%N %r"),+            Time::parse("0:01:02.345678901 0:01", "%T.%N %R"),+            Time::parse("0:01:02.345678901 02", "%T.%N %S"),+            Time::parse("0:01:02.345678901 0:01:02", "%T.%N %T"),+            Time::parse("1:00 am", "%-I:%M %p"),+            Time::parse("1:00 pm", "%-I:%M %p"),+            Time::parse(" 1:00 am", "%_I:%M %p"),+            Time::parse(" 1:00 pm", "%_I:%M %p"),+            Time::parse("01:00 am", "%0I:%M %p"),+            Time::parse("01:00 pm", "%0I:%M %p"),+            Time::parse("1:02:03.456789012 pm", "%-I:%M:%S.%N %p"),+            Time::parse("", ""),+        ));+    }++    parse_missing_seconds(ben: &mut Bencher) {+        ben.iter(|| (+            Time::parse("0:00", "%-H:%M"),+            Time::parse("23:59", "%H:%M"),+            Time::parse("12:00 am", "%I:%M %p"),+            Time::parse("12:00 pm", "%I:%M %p"),+        ));+    }++    parse_missing_minutes(ben: &mut Bencher) {+        ben.iter(|| (+            Time::parse("0", "%-H"),+            Time::parse("23", "%H"),+            Time::parse("12am", "%I%p"),+            Time::parse("12pm", "%I%p"),+        ));+    }++    display(ben: &mut Bencher) {+        let a = time!("0:00");+        let b = time!("23:59");+        let c = time!("23:59:59");+        let d = time!("0:00:01");+        let e = time!("0:00:00.001");+        let f = time!("0:00:00.000_001");+        let g = time!("0:00:00.000_000_001");++        ben.iter(|| (+            a.to_string(),+            b.to_string(),+            c.to_string(),+            d.to_string(),+            e.to_string(),+            f.to_string(),+            g.to_string(),+        ));+    }++    add_duration(ben: &mut Bencher) {+        let t = time!("0:00");+        let dta = 1.milliseconds();+        let dtb = 1.seconds();+        let dtc = 1.minutes();+        let dtd = 1.hours();+        let dte = 1.days();+        ben.iter(|| ((((t + dta) + dtb) + dtc) + dtd) + dte);

Yes, that is at least how the op traits are invoked in my experience. I think I wanted to make sure the compiler doesn't optimize the right-hand side, which could be relevant when the RHS is a primitive value but probably not here.

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

+use bench_util::setup_benchmark;+use time::{OffsetDateTime, UtcOffset};+use time_macros::offset;++setup_benchmark! {+    "UtcOffset",++    hours(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::hours(1),+            UtcOffset::hours(-1),+            UtcOffset::hours(23),+            UtcOffset::hours(-23),+        ));+    }++    directional_hours(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::east_hours(1),+            UtcOffset::west_hours(1),+        ));+    }++    minutes(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::minutes(1),+            UtcOffset::minutes(-1),+            UtcOffset::minutes(1_439),+            UtcOffset::minutes(-1_439),+        ));+    }++    directional_minutes(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::east_minutes(1),+            UtcOffset::west_minutes(1),+        ));+    }++    seconds(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::seconds(1),+            UtcOffset::seconds(-1),+            UtcOffset::seconds(86_399),+            UtcOffset::seconds(-86_399),+        ));+    }++    directional_seconds(ben: &mut Bencher) {+        ben.iter(|| (+            UtcOffset::east_seconds(1),+            UtcOffset::west_seconds(1),+        ));+    }++    as_hours(ben: &mut Bencher) {+        let a = offset!("+1");+        let b = offset!("+0:59");+        let c = offset!("-1");+        let d = offset!("-0:59");+        ben.iter(|| (+            a.as_hours(),+            b.as_hours(),+            c.as_hours(),+            d.as_hours(),+        ));+    }++    as_minutes(ben: &mut Bencher) {+        let a = offset!("+1");+        let b = offset!("+0:01");+        let c = offset!("+0:00:59");+        let d = offset!("-1");+        let e = offset!("-0:01");+        let f = offset!("-0:00:59");+        ben.iter(|| (+            a.as_minutes(),+            b.as_minutes(),+            c.as_minutes(),+            d.as_minutes(),+            e.as_minutes(),+            f.as_minutes(),+        ));+    }++    as_seconds(ben: &mut Bencher) {+        let a = offset!("+1");+        let b = offset!("+0:01");+        let c = offset!("+0:00:01");+        let d = offset!("-1");+        let e = offset!("-0:01");+        let f = offset!("-0:00:01");+        ben.iter(|| (+            a.as_seconds(),+            b.as_seconds(),+            c.as_seconds(),+            d.as_seconds(),+            e.as_seconds(),+            f.as_seconds(),+        ));+    }++    utc(ben: &mut Bencher) {+        ben.iter(|| offset!("UTC"));+    }

Hah, yeah, that looks silly now that you point it out. ^^

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

+use bench_util::setup_benchmark;+use time::error;++fn component_range() -> error::ComponentRange {+    time::Date::from_yo(0, 367).unwrap_err()+}++setup_benchmark! {+    "Parse error",++    display(ben: &mut Bencher) {+        let a = error::Parse::InvalidNanosecond;+        let b = error::Parse::InvalidSecond;+        let c = error::Parse::InvalidMinute;+        let d = error::Parse::InvalidHour;+        let e = error::Parse::InvalidAmPm;+        let f = error::Parse::InvalidMonth;+        let g = error::Parse::InvalidYear;+        let h = error::Parse::InvalidWeek;+        let i = error::Parse::InvalidDayOfWeek;+        let j = error::Parse::InvalidDayOfMonth;+        let k = error::Parse::InvalidDayOfYear;+        let l = error::Parse::InvalidOffset;+        let m = error::Parse::MissingFormatSpecifier;+        let n = error::Parse::InvalidFormatSpecifier('!');+        let o = error::Parse::UnexpectedCharacter {+            expected: 'a',+            actual: 'b',+        };+        let p = error::Parse::UnexpectedEndOfString;+        let q = error::Parse::InsufficientInformation;+        let r = error::Parse::ComponentOutOfRange(Box::new(component_range()));++        ben.iter(|| (+            a.to_string(), format!("{}", a),

Yeah, I think so too. I think I added it for syntax coverage or something like that, but on second thought that would belong in an ordinary unit test instead. And the two being in the same benchmarks even eliminates any possibility of noticing a would-be performance difference, so having both seems completely unnecessary.

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

 [package] name = "time-macros"-version = "0.1.0"+version = "0.1.1"

This is your commit. :slightly_smiling_face: Looks like you may have rebased the v0.3 branch since I rebased onto it, or something like that. Would you like me to rebase this to somewhere new?

emlun

comment created time in 10 days

PullRequestReviewEvent

Pull request review commenttime-rs/time

Add benchmarks

+[package]+name = "time-benchmarks"+publish = false+version = "0.0.0"+authors = ["Emil Lundberg <emil@emlun.se>"]+edition = "2018"+readme = "../README.md"+license = "MIT OR Apache-2.0"+description = "Benchmarks for the time crate."++[dev-dependencies]+criterion = "0.3"+bench-util = { path = "./bench-util" }+rand = { version = "0.7", default-features = false }+serde_json = "1"+standback = "0.2"

Oooh, I see. Sure, that works.

emlun

comment created time in 10 days

PullRequestReviewEvent

push eventemlun/time-rs

Emil Lundberg

commit sha 469920963257a0f41cd68fb4dc86652bf6f73aa3

Merge /time-benchmarks/.gitignore into /.gitignore

view details

Emil Lundberg

commit sha 563396a9d7757ec9fad9785ed6d115d80e58c24e

Rename Bencher argument to ben everywhere

view details

Emil Lundberg

commit sha 609f44c2d0a2836b0b7afc22723ad61283e51334

Reformat pattern for setup_benchmarks! Co-authored-by: Jacob Pratt <the.z.cuber@gmail.com>

view details

push time in 10 days

Pull request review commenttime-rs/time

Add benchmarks

+/// Helper macro that wraps code blocks in benchmark functions, and makes sure+/// to add all those functions to the Criterion benchmark group.+#[macro_export]+macro_rules! setup_benchmark {+    ($group_prefix:literal,++     $($(#[$fn_attr:meta])*+       $fn_name:ident ($bencher:ident : &mut Bencher)+       $code:block+     )*) => {

Why bother with multicursors when you can just sed -i 's/^\( *\)\([^ ].*mut Bencher\)/\1fn \2/' benches/*.rs? :wink:

emlun

comment created time in 10 days

PullRequestReviewEvent

push eventemlun/time-rs

Emil Lundberg

commit sha 8dfd33d0018fc5ac617c78946b4779d63b88a3ba

WIP: Reformat pattern for setup_benchmarks! Co-authored-by: Jacob Pratt <the.z.cuber@gmail.com>

view details

push time in 10 days

Pull request review commenttime-rs/time

Add benchmarks

+[package]+name = "time-benchmarks"+publish = false+version = "0.0.0"+authors = ["Emil Lundberg <emil@emlun.se>"]+edition = "2018"+readme = "../README.md"+license = "MIT OR Apache-2.0"+description = "Benchmarks for the time crate."++[dev-dependencies]+criterion = "0.3"+bench-util = { path = "./bench-util" }+rand = { version = "0.7", default-features = false }+serde_json = "1"+standback = "0.2"

Looks like Cargo doesn't allow you to import indirect dependencies, though (which is a good thing, in my opinion), so this needs to stay as far as I can tell.

emlun

comment created time in 10 days

PullRequestReviewEvent

issue commentcaddyserver/caddy

Tag v2.2.1 is not signed

You can also use git show <tag> to see that tag v2.2.0 is signed and v2.2.1 is not.

ArisuOngaku

comment created time in 13 days

Pull request review commentw3c/webauthn

Mention Intersection Observer v2 in sec considerations

 The main benefits offered to [=[WRPS]=] by this specification include: 1. The [=[RP]=] does not need to store additional secrets in order to gain the above benefits.  As stated in the [[#sctn-conforming-relying-parties|Conformance]] section, the [=[RP]=] MUST behave as described in [[#sctn-rp-operations]]-to obtain all of the above security benefits. However, one notable use case that departs slightly from this is described in the-next section.+to obtain all of the above security benefits. However, one notable use case that departs slightly from this is described below in [[#sctn-attestation-limitations]].+++### Visibility Considerations for Embedded Usage ### {#sctn-seccons-visibility}++Simplistic use of WebAuthn in an embedded context, e.g., within <{iframe}>s as described in [[#sctn-iframe-guidance]], may make one's users vulnerable to <dfn>UI Redressing</dfn> attacks, also know as "[Clickjacking](https://en.wikipedia.org/wiki/Clickjacking)". This is where an attacker overlays their own UI on top of a [=[RP]=]'s intended UI and attempt to trick the user into performing unintended actions with the [=[RP]=]. For example, using these techniques, an attacker might be able to serreptitiously trick users into unintended actions such as purchasing item(s), transferring money, etc.

Fixed a few grammar and spelling errors.

Suggestion: I don't think the "one's" in "one's users" is needed. "Surreptitiously" also seems redundant and could be unnecessarily obtuse to non-native-English readers, and if that is removed it makes sense to also deduplicate "unintended actions such as".

Simplistic use of WebAuthn in an embedded context, e.g., within <{iframe}>s as described in [[#sctn-iframe-guidance]], may make users vulnerable to <dfn>UI Redressing</dfn> attacks, also known as "[Clickjacking](https://en.wikipedia.org/wiki/Clickjacking)". This is where an attacker overlays their own UI on top of a [=[RP]=]'s intended UI and attempts to trick the user into performing unintended actions with the [=[RP]=]. For example, using these techniques, an attacker might be able to trick users into purchasing items, transferring money, etc.
equalsJeffH

comment created time in 13 days

PullRequestReviewEvent
PullRequestReviewEvent

issue commentgradle/gradle

Signing plugin doesn't work with GPG 2.1

Since Gradle 4.5.1 you can use the useGpgCmd() option of the signing plugin to use gpg-agent as the backend instead of Gradle's Java backend. This works fine for me in GPG 2.2.23, and also supports using smartcard keys.

bryant1410

comment created time in 13 days

push eventemlun/rush

Emil Lundberg

commit sha 4b5fadd07d3efd8ef4248664191018b5a839d49b

Simplify guard against recursive alias

view details

push time in 16 days

PR opened ashpil/rush

Implement alias/unalias builtin

Hello and happy Hacktoberfest! Here's a stab at implementing the alias/unalias builtin, along with a necessary bug fix (see 921fbeb611792d96b52b530663bfe1a74e4ac073 and 7d0511f262c2f485a790aeb6bb4970ffb75bb236) and some basic integration tests. I also extracted a debug_println! macro to make the assertions for those tests a bit cleaner.

What do you think?

+572 -8

0 comment

10 changed files

pr created time in 16 days

create barnchemlun/rush

branch : alias

created branch time in 16 days

fork emlun/rush

Basic rust POSIX shell

fork in 16 days

push eventemlun/time-rs

Emil Lundberg

commit sha 3bb9d411fe72dc7c315137c2a83b68b42270f8ac

Fix too long macro pattern

view details

push time in 16 days

push eventemlun/time-rs

Emil Lundberg

commit sha 8e07242de4c9af5eab167b147e9ffaca7ae98888

Fix too long macro pattern

view details

push time in 16 days

push eventemlun/time-rs

Emil Lundberg

commit sha 76737de795c85519e23fdc7e24aa64947d00e992

cargo +nightly fmt

view details

Emil Lundberg

commit sha 64411f5b445186daf5361e045b375e685f84598c

Fix too long lines

view details

push time in 16 days

pull request commenttime-rs/time

Add benchmarks

Judging by the Criterion docs, it at least looks like there isn't a nice and easy way to just enable it and go. cargo-criterion can produce JSON output that looks easy enough to inspect with a script, but cargo-criterion keeps crashing for me...

But on the other hand, the docs also warn about cloud CI giving unreliable results, so maybe a better way to go is to just have a script that makes it easy to run benchmark comparisons manually?

emlun

comment created time in 16 days

push eventemlun/time-rs

Emil Lundberg

commit sha 022986b1d54da6cf6c70fffbb485652b7c2122c7

Prevent publishing time-benchmarks crate

view details

Emil Lundberg

commit sha 85ca2c1600f25b848e0ba5167ed0450b129ffcc1

Move bench_util module to separate sub-crate The module was auto-detected by `cargo bench` as a benchmark, which caused issues such as making Criterion command line options crash the benchmark on unknown options. Moving it also means we can import the macro using a plain `use` statement instead of the `#[macro_use]` directive.

view details

push time in 16 days

more