Coder Social home page Coder Social logo

crypto-conditions's Introduction

Crypto-Conditions

Spec

You can find the spec here: https://tools.ietf.org/html/draft-thomas-crypto-conditions-04

The source code for the spec is in src/spec/crypto-conditions.md

Implementations

Known implementations of Crypto Conditions:

(Note that all of the above implementations currently need testing/updating. As soon as we have run a decent sized test suite against the implementations above, we'll provide the results here.)

If you would like to update this list, please feel free to open a pull request against this repository.

Test Vectors

In order to verify the different implementations, we provide a series of test vectors in JSON format. You can find them in the folder test-vectors. Within that folder, they are organized in the following subfolders:

  • valid - These are examples of valid crypto-conditions and their fulfillments. You should run the following tests against these:

    • Parse conditionBinary, serialize as a URI, should match conditionUri.
    • Parse conditionUri, serialize as binary, should match conditionBinary.
    • Parse fulfillment, serialize fulfillment, should match fulfillment.
    • Parse fulfillment and validate, should return true.
    • Parse fulfillment and generate the fingerprint contents
    • Parse fulfillment, generate the condition, serialize the condition as a URI, should match conditionUri.
    • Create fulfillment from json, serialize fulfillment, should match fulfillment.

    If a message field is provided, the condition should be evaluated against the message. Otherwise, an empty message should be passed to the verification function.

  • invalid - These are examples of intrinsically invalid fulfillments, such as an invalid signature or an encoding error.

    • Parse fulfillment and validate, should return error.

Note that we don't provide any test cases for fulfillments that are valid, but don't match the provided condition, because we can just include them in the valid set, which provides the exact condition that the fulfillment should map to. (Which is stricter than testing one of the nearly infinite possible conditions that it doesn't map to.)

Test Vectors Source

The test vectors themselves are generated from example data in the src/test-vectors/ folder. You should never have to worry about that unless you are adding or editing test vectors.

Generating Tests

The ffasn1dump tool is used to produce DER encodings. It is available from http://bellard.org/ffasn1

Generating the Spec

Uses kramdown-rfc2629, xml2rfc and Grunt with Grunt kramdown_rfc2629 task

From root directory of the repo run:

npm install
grunt kramdown_rfc2629

To watch edits to crypto-conditions.md and auto-generate output when changes are saved run:

grunt watch

crypto-conditions's People

Contributors

adrianhopebailie avatar andrew-g-za avatar ca333 avatar justmoon avatar sappenin avatar sbellem avatar ssadler avatar stevenroose avatar

Stargazers

 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

crypto-conditions's Issues

[test vectors] Should generated signatures be tested?

NOTE: The answer is obviously yes, but what I wonder is whether it should be added to the existing list under https://github.com/rfcs/crypto-conditions#test-vectors

See master...sbellem:test-vectors-signatures#diff-04c6e90faac2675aa89e2176d2eec7d8R35 for example.

The current list of things to test against the test vector does not include signing (for signature-based types: rsa & ed25519).

For example, if an implementation solely relies on the proposed list of things to test against the test vectors, the signature operation is simply untested. That is, the code of the signature operation is not executed at all during the test run.

We could add something like so to the existing list:

  • For signature-based types: generate the signature and check that it matches the given signature.

If that makes sense, I can create a PR for it.

One important detail

The test vectors should include the required secret information (e.g. private key for ed25519). This information is currently not in the test vectors but can be found under https://github.com/rfcs/crypto-conditions/tree/master/src/tests. For example, for the minimal ed25519 test vector, it is here: https://github.com/rfcs/crypto-conditions/blob/master/src/tests/minimal.js#L31

Test Vector 0008_test-basic-threshold has incorrect MaxMessageSize?

The java-crypto-conditions library has a failing TestVector test surrounding the maxMessageLength in one of the subconditions in 0008_test-basic-threshold.json.

Initially, I though this was a bug in the Java library, but looking more closely, the main threshold condition in test vector 0008_test-basic-threshold has a prefix-sha-256 subcondition with its own ed25519-sha-256 subcondition that signs the message "aaa" (in ASCII).

Since the prefix-sha-256 condition has a maxMessageLength set to 0, the overall threshold fulfillment verification in Java always fails because the message being verified is too long once it hits the prefix subcondition -- the message length violates the maxMessageLength checks in the Java code.

Shouldn't the json.subfulfillments['prefix-sha-256].maxMessageLength be 3 instead of 0?

Secp256k1 type

Wanted to get some feedback on this; would secp256k1 signature scheme be accepted into the spec? If so, with what type ID and interface? Have attached an example below. It doesn't use Bitcoin's pubkey hashing protocol; doesn't seem worth it.

If it's open for consideration, would be good to agree on a type ID. That way, if it does get integrated, I'll already be using the right one. ๐Ÿ™‚

See also: https://github.com/libscott/komodo/blob/73b9e32b9d7ede630af0df9bae8853cd9fa1b88a/src/script/interpreter.cpp#L939

--<ASN1.PDU Crypto-Conditions.Condition, Crypto-Conditions.Fulfillment>--

Crypto-Conditions DEFINITIONS AUTOMATIC TAGS ::= BEGIN

    -- Conditions

    Condition ::= CHOICE {
      preimageSha256   [0] SimpleSha256Condition,
      prefixSha256     [1] CompoundSha256Condition,
      thresholdSha256  [2] CompoundSha256Condition,
      rsaSha256        [3] SimpleSha256Condition,
      ed25519Sha256    [4] SimpleSha256Condition,
      secp256k1Sha256  [5] SimpleSha256Condition
    }

    SimpleSha256Condition ::= SEQUENCE {
      fingerprint          OCTET STRING (SIZE(32)),
      cost                 INTEGER (0..4294967295)
    }

    CompoundSha256Condition ::= SEQUENCE {
      fingerprint          OCTET STRING (SIZE(32)),
      cost                 INTEGER (0..4294967295),
      subtypes             ConditionTypes
    }

    ConditionTypes ::= BIT STRING {
      preImageSha256   (0),
      prefixSha256     (1),
      thresholdSha256  (2),
      rsaSha256        (3),
      ed25519Sha256    (4),
      secp256k1Sha256  (5)
    }
    
    -- Fulfillments

    Fulfillment ::= CHOICE {
      preimageSha256   [0] PreimageFulfillment ,
      prefixSha256     [1] PrefixFulfillment,
      thresholdSha256  [2] ThresholdFulfillment,
      rsaSha256        [3] RsaSha256Fulfillment,
      ed25519Sha256    [4] Ed25519Sha512Fulfillment,
      secp256k1Sha256  [5] Secp256k1Fulfillment
    }

    PreimageFulfillment ::= SEQUENCE {
      preimage             OCTET STRING
    }

    PrefixFulfillment ::= SEQUENCE {
      prefix               OCTET STRING,
      maxMessageLength     INTEGER (0..4294967295),
      subfulfillment       Fulfillment
    }

    ThresholdFulfillment ::= SEQUENCE {
      subfulfillments      SET OF Fulfillment,
      subconditions        SET OF Condition
    }

    RsaSha256Fulfillment ::= SEQUENCE {
      modulus              OCTET STRING,
      signature            OCTET STRING
    }

    Ed25519Sha512Fulfillment ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(32)),
      signature            OCTET STRING (SIZE(64))
    }

    Secp256k1Fulfillment ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(33)),
      signature            OCTET STRING (SIZE(64))

    -- Fingerprint Content

    -- The PREIMAGE-SHA-256 condition fingerprint content is not DER encoded
    -- The fingerprint content is the preimage

    PrefixFingerprintContents ::= SEQUENCE {
      prefix               OCTET STRING,
      maxMessageLength     INTEGER (0..4294967295),
      subcondition         Condition
    }

    ThresholdFingerprintContents ::= SEQUENCE {
      threshold            INTEGER (1..65535),
      subconditions2       SET OF Condition
    }
    
    RsaFingerprintContents ::= SEQUENCE {
      modulus              OCTET STRING
    }
    
    Ed25519FingerprintContents ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(32))
    }

    Secp256k1FingerprintContents ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(33))
    }

END

Clarify encoding of multi-value query-params in condition URIs

Section 9.2.3 of the crypto-condition spec currently defines the format of the subtypes URI query-parameter by mostly delegating to RFC-6920 and RFC-3986, which is al well and good.

However, these specs are somewhat ambiguous when it comes to comma-separated lists in a single query-param. For example, the following URIs are both valid per RFC-3986:

https://example.com?foo=bar,baz

https://example.com?foo=bar%2cbaz

The first URI treats the comma as a reserved character (which it is in query-params per RFC-3986), whereas the second URI encodes the comma-separator into the "foo" parameter, and relies upon contextual rules to determine the meaning, if any, of the commas.

I propose that the crypto-conditions spec clarify this by defining the use of commas as reserved URI characters, so URIs would look like this:

ni:///sha-256?fpt=ed25519-sha-256,prefix-sha-256&foo=a%20space

For deeper insight into what prompted this issue, please reference java-crypto-conditions/issues/50 and its proposed fix (PR 51) in the Java Crypto Conditions project.

Clarifying this minor point, as well as #8, will help in the creation of cross-platform compatibility testing to ensure that CryptoCondition URIs are being constructed properly.

Ordering of subtypes and query string parameters in URI form

The URI form of conditions should probably define some rules for determining equality. A direct string comparison is not appropriate because there are no rules that define the order of URI query strings nor the order of the subtypes.

The RFC should be explicit that URI normalization and comparison follow the rules as defined in RFC 3986 and the tests should folllow these rules for testing too

Typo in Section 4.2 of the spec

Was going through the new draft and just saw this:

4.2.  Multi-Signature
   ...
   That said, it is important that implementations must inspect the ypes and subtypes of any crypto-
   conditions they encounter to ensure they do not pass on a condition they will not be able to verify 
   at a later stage.
   ...

ypes should be types.

&subtypes= sorting in test vectors

The RFC document says of the subtypes parameter in the URI:

The list MUST be ordered by the type id value of each type, in ascending order. i.e. preimage-sha-256 MUST appear before prefix-sha-256.

This appears to be incorrect in the test vectors and also in the javascript code, which just uses the javascript .sort() method on the subtype names. Unless I'm missing something?

I'm working on a new implementation of crypto-conditions, I'll try to make a PR with some changes when it's more complete.

Question: Are CryptoConditions Verified or Validated?

This is a minor nit question (likely), but the spec uses the words verify and validate in seemingly identical circumstances. Because of this, certain implementations of the crypto-condtions spec are using different terminology for the same functions: For example, the Java implementation uses verify(...) whereas other implementations use validate(...).

I'm curious if anyone has opinions about which word should be used, or if both are synonymous? From the dictionary definitions, the two terms appear to be synonyms, but I'm curious if these terms have slightly different meanings in the field of cryptography:

Verify:

make sure or demonstrate that (something) is true, accurate, or justified.

Validate:

check or prove the validity or accuracy of (something).

RSA salt length

I recently started trying the RFC test vectors again against my implementation.

The RFC mentions

rSASSA-PSS-SHA256-Params RSASSA-PSS-params ::=  {
  hashAlgorithm        sha256Identifier,
  maskGenAlgorithm     mgf1SHA256Identifier,
  saltLength           20,
  trailerField         1
}

However, for me, my implementation fails the RSA vectors for salt length 20, but succeeds them for salt length 32.

Somewhat unclear sentence under section 7.1 Encoding Rules

The second paragraph under https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-7.1 says:

Alternative encodings may be used to represent top-level conditions
and fulfillments but to ensure a determinisitic outcome in producing
the condition fingerprint content, including any sub-conditions, MUST
be DER encoded prior to hashing.

I wonder whether the wording could be improved, or at least the punctuation, e.g.:

... but to ensure a determinisitic outcome in producing
the condition, the fingerprint content, including any sub-conditions, MUST
be DER encoded prior to hashing.

Wrong ASN.1 description for ed25519-sha-256

In the version 02 of the draft the condition and fulfillment ASN.1 representation for ed25519 is switched.
https://github.com/rfcs/crypto-conditions/blob/draft-02/src/spec/crypto-conditions.md#asn1-ed25519-sha-256-condition-asn1

The condition fingerprint is describing the fulfillment and the fulfillment is describing the fingerprint

### ASN.1 {#ed25519-sha-256-condition-asn1}

    -- Condition Fingerprint
    Ed25519Sha512Fulfillment ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(32)),
      signature            OCTET STRING (SIZE(64))
    }

    -- Fulfillment 
    Ed25519FingerprintContents ::= SEQUENCE {
      publicKey            OCTET STRING (SIZE(32))
    }

Subtypes not including root type

The spec says this:

Subtypes is a bitmap that indicates the set of types an implementation must support in order to be able to successfully validate the fulfillment of this condition. This is the set of types and subtypes of all sub-crypto-conditions, recursively excluding the type of the root crypto-condition.

If the root type is excluded, though. The subtypes set no longer represents all the types of the sub-conditions. In that case it's more like an "extra required types" field in that case.

For implementers it's only a minor issue (it means adding all subtypes recursively and removing the root type again in case it's also a subtype), but it's a little bit confusing.

Are there any JSON encoding rules?

Quoting from https://www.obj-sys.com/docs/JSONEncodingRules.pdf (2012) by Objective Systems, Inc.:

There is currently no recommendation from ITU-T, or any other standards body of which we are aware, that standardizes JSON encoding rules.

There's a related blog at https://www.obj-sys.com/blog/?p=508

Another company, OSS Nokalva, has a white paper: http://www.oss.com/asn1/resources/books-whitepapers-pubs/JSON%20Encoding%20Rules.pdf (2015).

I do not know how different, how alike, the two above approaches are.

What is crypto-conditions stance on this matter?


The current JSON representation of fulfillments in test vectors appears to be somewhat arbitrary, as the current specification does not mention any required JSON representation.

What are implementations to expect?

As an example, if one considers the json field in the following (minimal ed25519) test vector:

{
  "json": {
    "type": "ed25519-sha-256",
    "publicKey": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
    "signature": "5VZDAMNgrHKQhuLMgG6CioSHfx645dl02HPgZSJJAVVfuIIVkKM7rMYeOXAc-bRr0lv18FlbviRlUUFDjnoQCw"
  },
  "cost": 131072,
  "subtypes": [],
  "fingerprintContents": "30228020D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A",
  "fulfillment": "A4648020D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A8140E5564300C360AC729086E2CC806E828A84877F1EB8E5D974D873E065224901555FB8821590A33BACC61E39701CF9B46BD25BF5F0595BBE24655141438E7A100B",
  "conditionBinary": "A4278020799239ABA8FC4FF7EABFBC4C44E69E8BDFED993324E12ED64792ABE289CF1D5F8103020000",
  "conditionUri": "ni:///sha-256;eZI5q6j8T_fqv7xMROaei9_tmTMk4S7WR5Kr4onPHV8?fpt=ed25519-sha-256&cost=131072",
  "message": ""
}

implementations are expected to be capable to:

Create fulfillment from json, serialize fulfillment, should match fulfillment

(source: https://github.com/rfcs/crypto-conditions#test-vectors)

In other words an implementation should be able to consume

{
    "type": "ed25519-sha-256",
    "publicKey": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
    "signature": "5VZDAMNgrHKQhuLMgG6CioSHfx645dl02HPgZSJJAVVfuIIVkKM7rMYeOXAc-bRr0lv18FlbviRlUUFDjnoQCw"
}

and produce the fulfillment string (hexadecimal):

"A4648020D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A8140E5564300C360AC729086E2CC806E828A84877F1EB8E5D974D873E065224901555FB8821590A33BACC61E39701CF9B46BD25BF5F0595BBE24655141438E7A100B"

But different implementations could decide to diverge from the JSON representations found in the test vectors.

For example, leaving the content aside, as far as the representation (hex, base64, etc) is concerned, and paying attention to the structure, here are three very reasonable representations:

test vector

{
    "type": "ed25519-sha-256",
    "publicKey": "...",
    "signature": "..."
}

javascript asn1.js

{ 
    "type": "ed25519Sha256Fulfillment",
    "value": {
        "publicKey": "...",
        "signature": "..."
    }
}

python pyasn1

{
    "ed25519Sha256": {
        "publicKey": "...",
        "signature": "..."
    }
}

From an implementation's point of view it may be more convenient to actually stay closer to the representation used by the asn1 library that the implementation depends on, and this could easily lead to all kinds of variants of JSON schemas to represent both conditions, and fulfillments.

It seems to me that it may be worthwhile to attempt to have some kind of JER (JSON Encoding Rules), but I do not know enough about the complications that this may bring.

Lastly, as pointed out by @stevenroose in #10 the representation/encoding would need to be specified.

Clarify that PREIMAGE-SHA-256 conditions can be any length

Opening this issue on this repo as per interledger/rfcs#148


From @nbougalis

By the way, the "PREIMAGE-SHA-256" spec is a bit unclear about what's allowed in a preimage:

This type of condition is also called a "hashlock". By creating a hash of a difficult-to-guess 256-bit random or pseudo-random integer it is possible to create a condition which the creator can trivially fulfill by publishing the random value. However, for anyone else, the condition is cryptographically hard to fulfill, because they would have to find a preimage for the given condition hash.

This seems to suggest that only a 256-bit random integer is valid input, but the rest of the spec suggests otherwise.

Whether the intent is to give a condition that's the SHA-256 hash of a uint256 the special name "hashlock" or to explicitly limit PREIMAGE-SHA-256 to only 256-bit fulfillment sizes, the text fails.

I'd suggest:

By choosing an appropriately large and difficult-to-guess string of bytes, it is possible to create a condition which the creator can trivially fulfill by publishing the string of bytes. However, for anyone else, the condition is cryptographically hard to fulfill, because they would have to find a preimage for the given condition condition hash.
(edited)

Threshold Cryptoconditions Clarifications

This issue was originally submitted by @nbougalis at interledger/rfcs#209.

(Quoting from from @nbougalis)

The existing specification of THRESHOLD-SHA-256 can be somewhat confusing.

The standard should be amended to explicitly define that each sub-entry in an M-of-N threshold is given a hard-coded weight of exactly 1, and that for a valid fulfillment, the number of subfulfillments present will be exactly M. This means that the threshold can be derived by counting the subfulfillments present.

Additionally, althought implicit (since the condition generated from such a fulfillment won't match) the standard should, explicitly, specify that a fulfillment that contains (a) a number of subfulfillments other than exactly M; or (b) one where the number of subfullfilments and subconditions present is not exactly N is not valid.

Far from a simple optimization to save space, not including the count and requiring exactly M fulfillments has a valuable cryptographic purpose: to prevent malleability attacks. This is not mentioned anywhere. For completeness and as a precaution against an accidental future change that would compromise this critical property, we should add a paragraph or note that explains the rationale behind this.

To clarify, consider a 3-of-5 condition. Now, assume a fufillment for that condition is presented that contains 4 subfulfillments and 1 subcondition. Such a fulfillment, if it were to be valid against the condition, would contain one redundant signature. Removing any one at random and replacing it with its subcondition would result in a different but still valid fulfillment.

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.