From e5ee4ef23cc571a92b1fb917ed2f6b0220bb773d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 08:07:25 +0000 Subject: [PATCH 01/20] nep509 --- neps/nep-0509.md | 825 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 825 insertions(+) create mode 100644 neps/nep-0509.md diff --git a/neps/nep-0509.md b/neps/nep-0509.md new file mode 100644 index 000000000..0ab6279b1 --- /dev/null +++ b/neps/nep-0509.md @@ -0,0 +1,825 @@ +--- +NEP: 509 +Title: Rich Online Digital Token +Authors: Vicente Aceituno Canal +Status: New +DiscussionsTo: https://github.com/nearprotocol/neps/pull/519 +Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates +Version: 1.0.0 +Created: 2024-06-21 +LastUpdated: 2024-06-21 +--- + +## Summary +Properly designed custom non-fungible-tokens can complement or replace X.509 digital certificates for most purposes. The design presented in this NEP can be easily extended for any number of use cases that use digital certificates. among them, mutual authentication, electronic mail, digital signing and time stamping. + +## Motivation +Public Key Infrastructure is a prevalent way to use public key encryption. The original motivation of this NEP proposal are the many flaws in Public Key Infrastructure. It is beyond the scope of this NEP to explain these flaws in detail, please refer to the sources \[1\]\[2\]\[3\]\[4\]. + +Using blockchain issued tokens equivalent to digital certificates can provide better functionality than traditional digital certificates without compromising security. + +Currently there are no other NEP specifications covering this specific use case. + +Problems solved +--------------- +In this document we call the custom non-fungible-tokens used Rich Online Digital Tokens (RODiT for short). The problems solved are the following: +1. When implementing mutual authentication with X.509 digital certificates, the workflow has several steps, one of them requires transferring a file (CSR) between the endpoint and the CA. With RODiT we use a workflow with fewer steps, without file transfer, that is completed when the RODiT is sent (not installed), to a blockchain address. The impact of using a simpler process becomes highly significant as the number of participant nodes grows. +2. With X.509 digital certificates, key rotation requires issuing and installing a new digital certificate when the key is due to be rotated, regardless of the expiration date of the service being secured with the digital certificate. With RODiT, key rotation is decoupled from service expiration, as it does not require issuing a new RODiT. Key rotation using RODiT can be performed independently for every node, without any coordination between the parties, greatly simplifying the management of key rotation. +3. Rogue Certificate Authorities (Issuers in X.509 terminology) can generate digital certificates to any identifier, despite of Certificate Transparency and CAA records, making key pinning necessary in high security scenarios. Any X.509 Issuer can create a digital certificate for any domain name, while the legitimate owner of the domain name may not be aware it has been issued. While RODiT are based on smart contracts controlled by Issuers, it is the Service Providers that issue and revoke RODiT for the identifiers they control, and the Service Provider has the exclusive prerogative to authorize the smart contract. This prevents Unexpected Certificates as described in \[5\], making key pinning unnecessary. This NEP describes a mechanism for domain names use by service providers to declare what issuers are trusted to issue valid digital certificates for them, removing this threat. + +Potential use cases +------------------- +Rich Online Digital Tokens can be used as a complement or replacement of digital certificates for VPN authentication (reference implementation), SSH authentication and API authentication, among others. + +## Scope +This NEP includes RODiT structure with mandatory and optional fields. It does not include: + +* Governance of RODiT, who can create RODiT issuing smart contracts and how is their reputation determined. +* How RODiT field values are validated to be accurate, particularly when a field is an identifier or an address. +* How wallets interact via IPC or other mechanisms with applications using RODiT. + +## Terminology +Some terms are used with a specific meaning, as follows: +* **Rich Online Digital Token**: Abbreviated as RODiT, is a non fungible token which lifecycle and structure is conformant with this document. +* **Issuer**: The organization that creates a smart contract that is used by the Service Providers to mint their RODiT. +* **Service Provider**: Organization that signs its RODiT digitally and provides a service to users where RODiT are used for mutual authentication. +* **Holder**: A person or system that controls a RODiT via a key pair in a cryptographic wallet. + +## Specification +An implementing contract MUST include the following fields on-chain: + +| +**Field Name** + + | + +**Description** + + | + +**X.509 Equivalent** + + | + +**Type and Format** + + | + +**Default value and Valid Range** + + | +| --- | --- | --- | --- | --- | +| + +**versionnumber** + +(**NFT\_METADATA\_SPEC**) + + | + +Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. + + | + +Version Number + + | + +String + + | + +RODiT-near.org-MM.nn.rr + +MM: Major version + +nn: Minor version + +rr: revision + +M, m and r are decimal digits. + + | +| + +**symbol** + + | + +Symbol + + | + +Not Applicable + + | + +String + + | + +default value when implementing this standard without custom fields: RODiT + + | +| + +**base\_uri** + + | + +Smart Contract ID, serves as identification of the Issuer + + | + +Issuer Unique Identifier + + | + +URL to guarantee it is unique and controlled by a single entity + + | + +URL + + | +| + +**NFT\_STANDARD\_NAME** + + | + +Smart Contract Standard + + | + +No equivalent + + | + +String + + | + +NEP509 + + | + +For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] + +Note: +* MODIFIEDBASE\_URI is base\_uri, replacing the dot separating the TLD with the rest of the domain name with a dash “-”. +* SMARTCONTRACTID follows the following format: MMNNrr-MODIFIEDBASE\_URI.org + +An implementing Rich Online Digital Token MUST include the following fields on-chain: + +| +**Field Name** + + | + +**Description** + + | + +**X.509 Equivalent** + + | + +**Type and Format** + + | + +**Default value and Valid Range** + + | +| --- | --- | --- | --- | --- | +| + +**token\_id** + + | + +Unique ID of the token, must be randomly generated + + | + +Serial Number + + | + +String + + | + +For Service Provider is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER + +For Node is a String like: id=ULID + + | +| + +**issuer\_name** + + | + +Your Service Provider Name + + | + +Issuer Name + + | + +String + + | + +No default value / IT CAN BE EMPTY + + | +| + +**description\_rodt** + + | + +Description of your Service Provider + + | + +Not Applicable + + | + +String + + | + +No default value / IT CAN BE EMPTY + + | +| + +**not\_after** + + | + +Date of Expiration of Service + + | + +Not After + + | + +ISO 8601 YYYY/MM/DD + + | + +Default value one year from today’s day, must be greater than **not\_before**, and must take the value 1970/1/1 for “any” + + | +| + +**not\_before** + + | + +Date of Start of Service + + | + +Not Before + + | + +ISO 8601 YYYY/MM/DD + + | + +Default value today’s date, must take the value 1970/1/1 for “any” + + | +| + +**subjectuniqueidentifier\_url** + + | + +Service Provider URL + + | + +Subject Unique Identifier + + | + +URL to guarantee it is unique and controlled by a single entity + + | + +No default value, IT CAN NOT BE EMPTY + + | +| + +**serviceprovider\_id** + + | + +Service Provider ID + + | + +Not Applicable + + | + +String like + +id=ULID or SMARTCONTRACTID;id=ULID + + | + +For Service Provider is: ULIDOFTHESERVICEPROVIDER + +For Node is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER + + | +| + +**serviceprovider\_signature** + + | + +Ed25519 digital signature signed with the Private Key in Base58 + + | + +Certificate Signature + + | + +String of length 64 + + | + +No Default, Ed25519 digital signature (SHA384WITHECDSA), signed with the Private Key in Base58 + + | + +For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] + +The following X.509 fields are not implemented as part of RODiT by default, but practitioners may add custom fields with any information necessary for their use case: + +| +**X.509** + + | + +**Description** + + | +| --- | --- | +| + +Signature Algorithm ID + + | + +EdDSA when using ed22519 compatible blockchains, , blockchain dependent + + | +| + +Subject name + + | + +URLs, DNS entries, or Email addresses + + | +| + +Subject Public Key Info + + | + +Not applicable to RODiT, blockchain dependent + + | +| + +Public Key Algorithm + + | + +EdDSA when using ed22519 compatible blockchains, blockchain dependent + + | +| + +Subject Public Key + + | + +Not applicable to RODiT, blockchain dependent + + | +| + +Certificate Signature Algorithm + + | + +EdDSA when using ed22519 compatible blockchains, blockchain dependent + + | + +For sample implementation of custom fields see (examples with the fields cidrblock, listenport, dns, allowedips, kbpersecond): For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] + +## Interface +Metadata applies at both the contract level (`RodtContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: + +```java +export class RodtContractMetadata = { + versionnumber: string; + name: string; + symbol: string; + issueruniqueidentifierURL?: string; +} + +export class TokenMetadata { + issuername?: string; // Provider of the VPN Service + description?: string; // Description of the VPN Service + notafter?: string; // When the VPN Service expires, Unix epoch in milliseconds, 1 year by default in the user interface + notbefore?: string; // When the VPN Service starts, Unix epoch in milliseconds + subjectuniqueidentifierurl?: string; // Intial URL where the clients connect + serviceproviderid?: string; // Non fungible token ID of the "author" of the set of Non fungible tokens created + serviceprovidersignature?: string; // Hash of the Non fungible token signed with serviceproviderid's publickey sourced from the blockchain +} +``` + +A new attribute MUST be added to each `Token` struct: + +```java + export class Token { + owner_id: string; + approved_account_ids: { [accountId: string]: number }; + next_approval_id: number; + + constructor({ + ownerId, + approvedAccountIds, + nextApprovalId, + }: { + ownerId: string; + approvedAccountIds: { [accountId: string]: number }; + nextApprovalId: number; + }) +} +``` + +Service Provider root RODiT +--------------------------- + +| +**Field Name** + + | + +**Default value and Valid Range** + + | +| --- | --- | +| + +**token\_id** + + | + +SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER + + | +| + +**issuer\_name** + + | + +Service Provider issuer\_name + + | +| + +**description\_rodt** + + | + +Service Provider description\_rodt + + | +| + +**not\_after** + + | + +expiration date + + | +| + +**not\_before** + + | + +start date + + | +| + +**subjectuniqueidentifier\_url** + + | + +url of the Service Provider + + | +| + +**serviceprovider\_id** + + | + +ULIDOFTHESERVICEPROVIDER + + | +| + +**serviceprovider\_signature** + + | + +SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT (this RODiT) is sent upon creation + + | + +Service Provider server and client RODiT +---------------------------------------- + +| +**Field Name** + + | + +**Default value and Valid Range** + + | +| --- | --- | +| + +**token\_id** + + | + +id=ULID + + | +| + +**issuer\_name** + + | + +Service Provider issuer\_name + + | +| + +**description\_rodt** + + | + +Service Provider description\_rodt + + | +| + +**not\_after** + + | + +expiration date + + | +| + +**not\_before** + + | + +start date + + | +| + +**subjectuniqueidentifier\_url** + + | + +No default value + + | +| + +**serviceprovider\_id** + + | + +SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER + + | +| + +**serviceprovider\_signature** + + | + +SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT was sent upon creation + + | + + +Handling of RODiT +----------------- + +The reference implementation of RODiT uses implicit accounts ([https://docs.near.org/integrator/implicit-accounts](https://docs.near.org/integrator/implicit-accounts) ). Upon creation, RODiT can be sent to final addresses or to an address from where RODiT can be distributed to final endpoint addresses. Practitioners can use NEAR CLI or NEAR CLI RS to view the content of a RODiT or send it to an address. The reference implementation uses a bash script to make handling the RODiT sets more user friendly. It can be found here: [https://github.com/alanesmizi/cgwallet](https://github.com/alanesmizi/cgwallet) + +The script has the following options: + +* cgroditwallet.sh: List of available accounts + +* cgroditwallet.sh _accountID_: Lists the RODT Ids in the account and its balance + +* cgroditwallet.sh _accountID_ keys: Displays the accountID and the Private Key of the account + +* cgroditwallet.sh _accountID_ rodtId: Displays the indicated RODT + +* cgroditwallet.sh _fundingaccountId_ _unitializedaccountId_ init: Initializes account with 0.01 NEAR from funding acount + +* cgroditwallet.sh _originaccountId_ _destinationaccountId_ rodtId: Sends ROTD from origin account to destination account + +* cgroditwallet.sh genaccount: Creates a new uninitialized accountID + + +The key pair used for encryption can be rotated by sending the RODiT to a new address. + +Authentication with RODiT +------------------------- + +RODiT authentication is always mutual. The order for the checks and exchange protocol in the reference implementation uses the NOISE protocol (See [https://noiseprotocol.org/](https://noiseprotocol.org/)), as implemented in Wireguard ([https://www.wireguard.com/papers/wireguard.pdf](https://www.wireguard.com/papers/wireguard.pdf)), with the following steps: Initiation, Response and Confirmation. + +Both endpoints check that the peer can pass the following checks: + +1. Possession: The endpoint signs the token\_id (somehow equivalent to CertificateVerify in X.509) with the private key of the RODiT address, sends the token\_id and the signature to the peer. Upon reception the peer fetches from the blockchain the public key where the token\_id is, and checks the signature. (Notes: There is not certificate request as when using digital certificates) **Do I need to add the SMARTCONTRACTID to the handshake?** The reference implementation uses the function _pub fn verify\_hasrodt\_getit_ for this check. +2. Genuine: The endpoint fetches from the blockchain the public key where the serviceprovider\_id of the own RODiT is, and checks the serviceprovider\_signature against the peer’s RODiT token\_id and the fetched public key. The reference implementation uses the function _pub fn verify\_rodt\_isamatch_ for this check. +3. Live: The endpoint checks the current time and date against the not\_after and not\_before fields of the peer’s RODiT. The reference implementation uses the function _pub fn verify\_rodt\_islive_ for this check. +4. Active: The endpoint checks if there is a DNS entry using the peer’s RODiT token\_id that follows the format _token\_id.revoked.subjectuniqueidentifierurl_. If the entry exists, the RODiT has been revoked. The reference implementation uses the function _pub fn verify\_rodt\_isactive_ for this check. +5. Legitimate: The endpoint checks if the Issuer is legitimate, in other words, if it has been authorized by the Service Provider to issue RODiT for its subjectuniqueidentifierurl, by checking if there is a DNS entry using the peer’s RODiT token\_id that follows the format _SMARTCONTRACTID.smartcontract.subjectuniqueidentifierurl_. If the entry does not exists, the smart contract has been revoked. The reference implementation uses the function _pub fn verify\_rodt\_smartcontract\_istrusted_ for this check. (Note: Do we need to check if the RODiT root is Live and Active) +6. Valid: The endpoint may check optional properties of the RODiT, like location, number of transactions per minute, among other use cases. + +Reference Implementation - Minimum Viable Interface +--------------------------------------------------- + +traits and structs for rust + +interfaces and classes for java script + +Security Implications +--------------------- +RODiT offer robust security features, including: +* Mutual authentication by default. +* Explicit authorization of Issuers preventing person in the middle attacks. +* Easy detection and recovery from key compromise. As the RODiT is associated with a blockchain address, the only way the attacker can keep exclusive control of the RODiT is moving it to a new address. This can be observed publicly as soon as it happens. Besides, as RODiT can only be verified online, so all parties will react immediately to the RODiT being revoked an will not accept it. Man in the middle attacks are far more challenging using RODiT than X.509 certificates, as we can verify validity against multiple RPC providers or even have our own local NEAR node. + +Alternatives +------------ + +RODiT have been developed as an alternative to X.509 digital certificates. + +Future possibilities +-------------------- + +RODiT could be used as personal user accounts not connected to any directory, with fields like: +* **locationofbirth**: Place of birth in plus code format +* **dateandtimeofbirth**: Date and time of birth in GeneralizedTime format or RFC3339 +* **namesshared**: Part of the full name shared with family (this is known as surname in some countries) +* **namesnotshared**: Part of the full name not shared with family (this is known as name in some countries) +* **taxresidence**: Tax residence as a ISO 3166-1 alpha2-2 country code +* **taxpayercode**: Tax payer code +* **phonenumber**: Contact phone number +* **postaddress**: Contact address in plus code format + +RODiT can also be used for SSH authentication and API authentication. + +Consequences +------------ + +### Positive + +* consequence + + +### Negative + +* consequence + + +### Backwards Compatibility +There is no need to backwards compatibility as RODiT have a use case fundamentally different from Non-fungible tokens. + +Unresolved Issues (Optional) +---------------------------- + +RODiT use implicit accounts at the moment due to cryptographic wallets missing any kind of interface with other software, for example browsers. The utility of RODiT will be limited to technical use cases until an interface is developed. + +Changelog +--------- +Version 1.0.0 Submitted for approval + +References +---------- + +1. [https://www.schneier.com/wp-content/uploads/2016/02/paper-pki.pdf](https://www.schneier.com/wp-content/uploads/2016/02/paper-pki.pdf) + +2. [https://datatracker.ietf.org/doc/html/draft-housley-web-pki-problems-00.txt](https://datatracker.ietf.org/doc/html/draft-housley-web-pki-problems-00.txt) + +3. [https://www.iang.org/ssl/pki\_considered\_harmful.html](https://www.iang.org/ssl/pki_considered_harmful.html) + +4. [https://sslmate.com/resources/certificate\_authority\_failures](https://sslmate.com/resources/certificate_authority_failures) + +5. [https://datatracker.ietf.org/doc/html/draft-housley-web-pki-problems-00](https://datatracker.ietf.org/doc/html/draft-housley-web-pki-problems-00) + + +### 1.0.0 - Initial Version + +> Placeholder for the context about when and who approved this NEP version. + +#### Benefits + +> List of benefits filled by the Subject Matter Experts while reviewing this version: + +* Benefit 1 + +* Benefit 2 + + +#### Concerns + +> Template for Subject Matter Experts review for this version: Status: New | Ongoing | Resolved + +| +# + + | + +Concern + + | + +Resolution + + | + +Status + + | +| --- | --- | --- | --- | +| + +1 + + | + + | + + | + + | +| + +2 + + | + + | + + | + + | + +Copyright +--------- + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file From 0ed468ebce87cbcfe8fe8940ce8ca1ebb2fa0d7a Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:26:39 +0200 Subject: [PATCH 02/20] Update nep-0509.md --- neps/nep-0509.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 0ab6279b1..d6e9a83b2 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -3,6 +3,7 @@ NEP: 509 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal Status: New +| DiscussionsTo: https://github.com/nearprotocol/neps/pull/519 Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates Version: 1.0.0 @@ -822,4 +823,4 @@ Status Copyright --------- -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 5e9b882971c3615f69a717d45d94409e2fcba1bf Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:26:51 +0200 Subject: [PATCH 03/20] Update nep-0509.md --- neps/nep-0509.md | 1 - 1 file changed, 1 deletion(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index d6e9a83b2..49c561589 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -3,7 +3,6 @@ NEP: 509 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal Status: New -| DiscussionsTo: https://github.com/nearprotocol/neps/pull/519 Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates Version: 1.0.0 From 807698a06e08a27a87435274cf45bd8ad87accfb Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:33:11 +0200 Subject: [PATCH 04/20] Update nep-0509.md --- neps/nep-0509.md | 118 +++-------------------------------------------- 1 file changed, 7 insertions(+), 111 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 49c561589..104299f51 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -48,121 +48,17 @@ Some terms are used with a specific meaning, as follows: ## Specification An implementing contract MUST include the following fields on-chain: -| -**Field Name** - - | - -**Description** - - | - -**X.509 Equivalent** - - | - -**Type and Format** - - | - -**Default value and Valid Range** - - | +| **Field Name** | **Description** | **X.509 Equivalent** | **Type and Format** | **Default value and Valid Range** | | --- | --- | --- | --- | --- | -| - -**versionnumber** - -(**NFT\_METADATA\_SPEC**) - - | - -Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. - - | - -Version Number - - | - -String - - | - -RODiT-near.org-MM.nn.rr - +| Cell 1, Row 1 | Cell 2, Row 1 | +| **versionnumber** (**NFT\_METADATA\_SPEC**) | Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. | Version Number | String | RODiT-near.org-MM.nn.rr MM: Major version - nn: Minor version - rr: revision - -M, m and r are decimal digits. - - | -| - -**symbol** - - | - -Symbol - - | - -Not Applicable - - | - -String - - | - -default value when implementing this standard without custom fields: RODiT - - | -| - -**base\_uri** - - | - -Smart Contract ID, serves as identification of the Issuer - - | - -Issuer Unique Identifier - - | - -URL to guarantee it is unique and controlled by a single entity - - | - -URL - - | -| - -**NFT\_STANDARD\_NAME** - - | - -Smart Contract Standard - - | - -No equivalent - - | - -String - - | - -NEP509 - - | +M, m and r are decimal digits. | +| **symbol** | Symbol | Not Applicable | String | default value when implementing this standard without custom fields: RODiT | +| **base\_uri** | Smart Contract ID, serves as identification of the Issuer | Issuer Unique Identifier | URL to guarantee it is unique and controlled by a single entity | URL | +| **NFT\_STANDARD\_NAME** | Smart Contract Standard | No equivalent | String | NEP509 | For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] From 5a0964564a74a1f29c44a269cb0e1a6ed14d5d88 Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:35:08 +0200 Subject: [PATCH 05/20] Update nep-0509.md --- neps/nep-0509.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 104299f51..2ea886d31 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -51,11 +51,7 @@ An implementing contract MUST include the following fields on-chain: | **Field Name** | **Description** | **X.509 Equivalent** | **Type and Format** | **Default value and Valid Range** | | --- | --- | --- | --- | --- | | Cell 1, Row 1 | Cell 2, Row 1 | -| **versionnumber** (**NFT\_METADATA\_SPEC**) | Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. | Version Number | String | RODiT-near.org-MM.nn.rr -MM: Major version -nn: Minor version -rr: revision -M, m and r are decimal digits. | +| **versionnumber** (**NFT\_METADATA\_SPEC**) | Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. | Version Number | String | RODiT-near.org-MM.nn.rr , MM: Major version , nn: Minor version , rr: revision , where M, m and r are decimal digits. | | **symbol** | Symbol | Not Applicable | String | default value when implementing this standard without custom fields: RODiT | | **base\_uri** | Smart Contract ID, serves as identification of the Issuer | Issuer Unique Identifier | URL to guarantee it is unique and controlled by a single entity | URL | | **NFT\_STANDARD\_NAME** | Smart Contract Standard | No equivalent | String | NEP509 | From b8e380315eb7e89af52e839170724736ff766713 Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:06:27 +0200 Subject: [PATCH 06/20] Update nep-0509.md --- neps/nep-0509.md | 514 ++++------------------------------------------- 1 file changed, 39 insertions(+), 475 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 2ea886d31..185d557e9 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -3,7 +3,7 @@ NEP: 509 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal Status: New -DiscussionsTo: https://github.com/nearprotocol/neps/pull/519 +DiscussionsTo: https://github.com/nearprotocol/neps/pull/509 Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates Version: 1.0.0 Created: 2024-06-21 @@ -64,271 +64,31 @@ Note: An implementing Rich Online Digital Token MUST include the following fields on-chain: -| -**Field Name** - - | - -**Description** - - | - -**X.509 Equivalent** - - | - -**Type and Format** - - | - -**Default value and Valid Range** - - | +| **Field Name** | **Description** | **X.509 Equivalent** | **Type and Format** | **Default value and Valid Range** | | --- | --- | --- | --- | --- | -| - -**token\_id** - - | - -Unique ID of the token, must be randomly generated - - | - -Serial Number - - | - -String - - | - -For Service Provider is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER - -For Node is a String like: id=ULID - - | -| - -**issuer\_name** - - | - -Your Service Provider Name - - | - -Issuer Name - - | - -String - - | - -No default value / IT CAN BE EMPTY - - | -| - -**description\_rodt** - - | - -Description of your Service Provider - - | - -Not Applicable - - | - -String - - | - -No default value / IT CAN BE EMPTY - - | -| - -**not\_after** - - | - -Date of Expiration of Service - - | - -Not After - - | - -ISO 8601 YYYY/MM/DD - - | - -Default value one year from today’s day, must be greater than **not\_before**, and must take the value 1970/1/1 for “any” - - | -| - -**not\_before** - - | - -Date of Start of Service - - | - -Not Before - - | - -ISO 8601 YYYY/MM/DD - - | - -Default value today’s date, must take the value 1970/1/1 for “any” - - | -| - -**subjectuniqueidentifier\_url** - - | - -Service Provider URL - - | - -Subject Unique Identifier - - | - -URL to guarantee it is unique and controlled by a single entity - - | - -No default value, IT CAN NOT BE EMPTY - - | -| - -**serviceprovider\_id** - - | - -Service Provider ID - - | - -Not Applicable - - | - -String like - -id=ULID or SMARTCONTRACTID;id=ULID - - | - -For Service Provider is: ULIDOFTHESERVICEPROVIDER - -For Node is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER - - | -| - -**serviceprovider\_signature** - - | - -Ed25519 digital signature signed with the Private Key in Base58 - - | - -Certificate Signature - - | - -String of length 64 - - | - -No Default, Ed25519 digital signature (SHA384WITHECDSA), signed with the Private Key in Base58 - - | +| **token\_id** | Unique ID of the token, must be randomly generated | Serial Number | String | For Service Provider is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER, For Node is a String like: id=ULID | +| **issuer\_name** | Your Service Provider Name | Issuer Name | String | No default value / IT CAN BE EMPTY | +| **description\_rodt** | Description of your Service Provider | Not Applicable | String | No default value / IT CAN BE EMPTY | +| **not\_after** | Date of Expiration of Service | Not After | ISO 8601 YYYY/MM/DD | Default value one year from today’s day, must be greater than **not\_before**, and must take the value 1970/1/1 for “any” | +| **not\_before** | Date of Start of Service | Not Before | ISO 8601 YYYY/MM/DD | Default value today’s date, must take the value 1970/1/1 for “any” | +| **subjectuniqueidentifier\_url** | Service Provider URL | Subject Unique Identifier | URL to guarantee it is unique and controlled by a single entity | No default value, IT CAN NOT BE EMPTY | +| **serviceprovider\_id** | Service Provider ID | Not Applicable | String likeid=ULID or SMARTCONTRACTID;id=ULID | For Service Provider is: ULIDOFTHESERVICEPROVIDER, For Node is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER | +| **serviceprovider\_signature** | Ed25519 digital signature signed with the Private Key in Base58 | Certificate Signature | String of length 64 | No Default, Ed25519 digital signature (SHA384WITHECDSA), signed with the Private Key in Base58 | For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] The following X.509 fields are not implemented as part of RODiT by default, but practitioners may add custom fields with any information necessary for their use case: -| -**X.509** - - | - -**Description** - - | +| **X.509** | **Description** | | --- | --- | -| - -Signature Algorithm ID - - | - -EdDSA when using ed22519 compatible blockchains, , blockchain dependent - - | -| - -Subject name - - | - -URLs, DNS entries, or Email addresses - - | -| - -Subject Public Key Info - - | - -Not applicable to RODiT, blockchain dependent - - | -| - -Public Key Algorithm - - | - -EdDSA when using ed22519 compatible blockchains, blockchain dependent - - | -| - -Subject Public Key +| Signature Algorithm ID | EdDSA when using ed22519 compatible blockchains, , blockchain dependent | +| Subject name | URLs, DNS entries, or Email addresses | +| Subject Public Key Info | Not applicable to RODiT, blockchain dependent | +| Public Key Algorithm | EdDSA when using ed22519 compatible blockchains, blockchain dependent | +| Subject Public Key | Not applicable to RODiT, blockchain dependent | +| Certificate Signature Algorithm | EdDSA when using ed22519 compatible blockchains, blockchain dependent | - | - -Not applicable to RODiT, blockchain dependent - - | -| - -Certificate Signature Algorithm - - | - -EdDSA when using ed22519 compatible blockchains, blockchain dependent - - | - -For sample implementation of custom fields see (examples with the fields cidrblock, listenport, dns, allowedips, kbpersecond): For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] +For sample implementation of custom fields see (examples with the fields cidrblock, listenport, dns, allowedips): For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] ## Interface Metadata applies at both the contract level (`RodtContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: @@ -375,172 +135,30 @@ A new attribute MUST be added to each `Token` struct: Service Provider root RODiT --------------------------- -| -**Field Name** - - | - -**Default value and Valid Range** - - | +| **Field Name** | **Default value and Valid Range** | | --- | --- | -| - -**token\_id** - - | - -SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER - - | -| - -**issuer\_name** - - | - -Service Provider issuer\_name - - | -| - -**description\_rodt** - - | - -Service Provider description\_rodt - - | -| - -**not\_after** - - | - -expiration date - - | -| - -**not\_before** - - | - -start date - - | -| - -**subjectuniqueidentifier\_url** - - | - -url of the Service Provider - - | -| - -**serviceprovider\_id** - - | - -ULIDOFTHESERVICEPROVIDER - - | -| - -**serviceprovider\_signature** - - | - -SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT (this RODiT) is sent upon creation - - | +| **token\_id** | SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER | +| **issuer\_name** | Service Provider issuer\_name | +| **description\_rodt** | Service Provider description\_rodt | +| **not\_after** | expiration date | +| **not\_before** | start date | +| **subjectuniqueidentifier\_url** | url of the Service Provider | +| **serviceprovider\_id** | ULIDOFTHESERVICEPROVIDER | +| **serviceprovider\_signature** | SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT (this RODiT) is sent upon creation | Service Provider server and client RODiT ---------------------------------------- -| -**Field Name** - - | - -**Default value and Valid Range** - - | +| **Field Name** | **Default value and Valid Range** | | --- | --- | -| - -**token\_id** - - | - -id=ULID - - | -| - -**issuer\_name** - - | - -Service Provider issuer\_name - - | -| - -**description\_rodt** - - | - -Service Provider description\_rodt - - | -| - -**not\_after** - - | - -expiration date - - | -| - -**not\_before** - - | - -start date - - | -| - -**subjectuniqueidentifier\_url** - - | - -No default value - - | -| - -**serviceprovider\_id** - - | - -SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER - - | -| - -**serviceprovider\_signature** - - | - -SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT was sent upon creation - - | +| **token\_id** | id=ULID | +| **issuer\_name** | Service Provider issuer\_name | +| **description\_rodt** | Service Provider description\_rodt | +| **not\_after** | expiration date | +| **not\_before** | start date | +| **subjectuniqueidentifier\_url** | No default value | +| **serviceprovider\_id** | SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER | +| **serviceprovider\_signature** | SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT was sent upon creation | Handling of RODiT @@ -549,21 +167,13 @@ Handling of RODiT The reference implementation of RODiT uses implicit accounts ([https://docs.near.org/integrator/implicit-accounts](https://docs.near.org/integrator/implicit-accounts) ). Upon creation, RODiT can be sent to final addresses or to an address from where RODiT can be distributed to final endpoint addresses. Practitioners can use NEAR CLI or NEAR CLI RS to view the content of a RODiT or send it to an address. The reference implementation uses a bash script to make handling the RODiT sets more user friendly. It can be found here: [https://github.com/alanesmizi/cgwallet](https://github.com/alanesmizi/cgwallet) The script has the following options: - * cgroditwallet.sh: List of available accounts - * cgroditwallet.sh _accountID_: Lists the RODT Ids in the account and its balance - * cgroditwallet.sh _accountID_ keys: Displays the accountID and the Private Key of the account - * cgroditwallet.sh _accountID_ rodtId: Displays the indicated RODT - * cgroditwallet.sh _fundingaccountId_ _unitializedaccountId_ init: Initializes account with 0.01 NEAR from funding acount - * cgroditwallet.sh _originaccountId_ _destinationaccountId_ rodtId: Sends ROTD from origin account to destination account - * cgroditwallet.sh genaccount: Creates a new uninitialized accountID - The key pair used for encryption can be rotated by sending the RODiT to a new address. @@ -597,7 +207,6 @@ RODiT offer robust security features, including: Alternatives ------------ - RODiT have been developed as an alternative to X.509 digital certificates. Future possibilities @@ -619,14 +228,10 @@ Consequences ------------ ### Positive - * consequence - ### Negative - * consequence - ### Backwards Compatibility There is no need to backwards compatibility as RODiT have a use case fundamentally different from Non-fungible tokens. @@ -655,63 +260,22 @@ References ### 1.0.0 - Initial Version - > Placeholder for the context about when and who approved this NEP version. #### Benefits - > List of benefits filled by the Subject Matter Experts while reviewing this version: - * Benefit 1 - * Benefit 2 - #### Concerns > Template for Subject Matter Experts review for this version: Status: New | Ongoing | Resolved -| -# - - | - -Concern - - | - -Resolution - - | - -Status - - | +| # | Concern | Resolution | Status | | --- | --- | --- | --- | -| - -1 - - | - - | - - | - - | -| - -2 - - | - - | - - | - - | +| 1 | | | | +| 2 | | | | Copyright --------- - Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 8a4399f60efdc46ee0e3ccd2589277417bb1c049 Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:08:55 +0200 Subject: [PATCH 07/20] Update nep-0509.md --- neps/nep-0509.md | 1 - 1 file changed, 1 deletion(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 185d557e9..ea5abfc23 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -50,7 +50,6 @@ An implementing contract MUST include the following fields on-chain: | **Field Name** | **Description** | **X.509 Equivalent** | **Type and Format** | **Default value and Valid Range** | | --- | --- | --- | --- | --- | -| Cell 1, Row 1 | Cell 2, Row 1 | | **versionnumber** (**NFT\_METADATA\_SPEC**) | Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. | Version Number | String | RODiT-near.org-MM.nn.rr , MM: Major version , nn: Minor version , rr: revision , where M, m and r are decimal digits. | | **symbol** | Symbol | Not Applicable | String | default value when implementing this standard without custom fields: RODiT | | **base\_uri** | Smart Contract ID, serves as identification of the Issuer | Issuer Unique Identifier | URL to guarantee it is unique and controlled by a single entity | URL | From f2c11c8cb00d2064180cfa76bf6937a8fb233457 Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:13:55 +0200 Subject: [PATCH 08/20] Update nep-0509.md --- neps/nep-0509.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index ea5abfc23..0c456bb05 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -67,7 +67,7 @@ An implementing Rich Online Digital Token MUST include the following fields on-c | --- | --- | --- | --- | --- | | **token\_id** | Unique ID of the token, must be randomly generated | Serial Number | String | For Service Provider is a String like SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER, For Node is a String like: id=ULID | | **issuer\_name** | Your Service Provider Name | Issuer Name | String | No default value / IT CAN BE EMPTY | -| **description\_rodt** | Description of your Service Provider | Not Applicable | String | No default value / IT CAN BE EMPTY | +| **description\_rodit** | Description of your Service Provider | Not Applicable | String | No default value / IT CAN BE EMPTY | | **not\_after** | Date of Expiration of Service | Not After | ISO 8601 YYYY/MM/DD | Default value one year from today’s day, must be greater than **not\_before**, and must take the value 1970/1/1 for “any” | | **not\_before** | Date of Start of Service | Not Before | ISO 8601 YYYY/MM/DD | Default value today’s date, must take the value 1970/1/1 for “any” | | **subjectuniqueidentifier\_url** | Service Provider URL | Subject Unique Identifier | URL to guarantee it is unique and controlled by a single entity | No default value, IT CAN NOT BE EMPTY | @@ -90,10 +90,10 @@ The following X.509 fields are not implemented as part of RODiT by default, but For sample implementation of custom fields see (examples with the fields cidrblock, listenport, dns, allowedips): For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] ## Interface -Metadata applies at both the contract level (`RodtContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: +Metadata applies at both the contract level (`RoditContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: ```java -export class RodtContractMetadata = { +export class RoditContractMetadata = { versionnumber: string; name: string; symbol: string; @@ -138,7 +138,7 @@ Service Provider root RODiT | --- | --- | | **token\_id** | SMARTCONTRACTID;id=ULIDOFTHESERVICEPROVIDER | | **issuer\_name** | Service Provider issuer\_name | -| **description\_rodt** | Service Provider description\_rodt | +| **description\_rodit** | Service Provider description\_rodit | | **not\_after** | expiration date | | **not\_before** | start date | | **subjectuniqueidentifier\_url** | url of the Service Provider | @@ -152,7 +152,7 @@ Service Provider server and client RODiT | --- | --- | | **token\_id** | id=ULID | | **issuer\_name** | Service Provider issuer\_name | -| **description\_rodt** | Service Provider description\_rodt | +| **description\_rodit** | Service Provider description\_rodit | | **not\_after** | expiration date | | **not\_before** | start date | | **subjectuniqueidentifier\_url** | No default value | @@ -167,11 +167,11 @@ The reference implementation of RODiT uses implicit accounts ([https://docs.near The script has the following options: * cgroditwallet.sh: List of available accounts -* cgroditwallet.sh _accountID_: Lists the RODT Ids in the account and its balance +* cgroditwallet.sh _accountID_: Lists the RODiT Ids in the account and its balance * cgroditwallet.sh _accountID_ keys: Displays the accountID and the Private Key of the account -* cgroditwallet.sh _accountID_ rodtId: Displays the indicated RODT +* cgroditwallet.sh _accountID_ roditId: Displays the indicated RODiT * cgroditwallet.sh _fundingaccountId_ _unitializedaccountId_ init: Initializes account with 0.01 NEAR from funding acount -* cgroditwallet.sh _originaccountId_ _destinationaccountId_ rodtId: Sends ROTD from origin account to destination account +* cgroditwallet.sh _originaccountId_ _destinationaccountId_ roditId: Sends ROTD from origin account to destination account * cgroditwallet.sh genaccount: Creates a new uninitialized accountID The key pair used for encryption can be rotated by sending the RODiT to a new address. @@ -183,11 +183,11 @@ RODiT authentication is always mutual. The order for the checks and exchange pro Both endpoints check that the peer can pass the following checks: -1. Possession: The endpoint signs the token\_id (somehow equivalent to CertificateVerify in X.509) with the private key of the RODiT address, sends the token\_id and the signature to the peer. Upon reception the peer fetches from the blockchain the public key where the token\_id is, and checks the signature. (Notes: There is not certificate request as when using digital certificates) **Do I need to add the SMARTCONTRACTID to the handshake?** The reference implementation uses the function _pub fn verify\_hasrodt\_getit_ for this check. -2. Genuine: The endpoint fetches from the blockchain the public key where the serviceprovider\_id of the own RODiT is, and checks the serviceprovider\_signature against the peer’s RODiT token\_id and the fetched public key. The reference implementation uses the function _pub fn verify\_rodt\_isamatch_ for this check. -3. Live: The endpoint checks the current time and date against the not\_after and not\_before fields of the peer’s RODiT. The reference implementation uses the function _pub fn verify\_rodt\_islive_ for this check. -4. Active: The endpoint checks if there is a DNS entry using the peer’s RODiT token\_id that follows the format _token\_id.revoked.subjectuniqueidentifierurl_. If the entry exists, the RODiT has been revoked. The reference implementation uses the function _pub fn verify\_rodt\_isactive_ for this check. -5. Legitimate: The endpoint checks if the Issuer is legitimate, in other words, if it has been authorized by the Service Provider to issue RODiT for its subjectuniqueidentifierurl, by checking if there is a DNS entry using the peer’s RODiT token\_id that follows the format _SMARTCONTRACTID.smartcontract.subjectuniqueidentifierurl_. If the entry does not exists, the smart contract has been revoked. The reference implementation uses the function _pub fn verify\_rodt\_smartcontract\_istrusted_ for this check. (Note: Do we need to check if the RODiT root is Live and Active) +1. Possession: The endpoint signs the token\_id (somehow equivalent to CertificateVerify in X.509) with the private key of the RODiT address, sends the token\_id and the signature to the peer. Upon reception the peer fetches from the blockchain the public key where the token\_id is, and checks the signature. (Notes: There is not certificate request as when using digital certificates) **Do I need to add the SMARTCONTRACTID to the handshake?** The reference implementation uses the function _pub fn verify\_hasrodit\_getit_ for this check. +2. Genuine: The endpoint fetches from the blockchain the public key where the serviceprovider\_id of the own RODiT is, and checks the serviceprovider\_signature against the peer’s RODiT token\_id and the fetched public key. The reference implementation uses the function _pub fn verify\_rodit\_isamatch_ for this check. +3. Live: The endpoint checks the current time and date against the not\_after and not\_before fields of the peer’s RODiT. The reference implementation uses the function _pub fn verify\_rodit\_islive_ for this check. +4. Active: The endpoint checks if there is a DNS entry using the peer’s RODiT token\_id that follows the format _token\_id.revoked.subjectuniqueidentifierurl_. If the entry exists, the RODiT has been revoked. The reference implementation uses the function _pub fn verify\_rodit\_isactive_ for this check. +5. Legitimate: The endpoint checks if the Issuer is legitimate, in other words, if it has been authorized by the Service Provider to issue RODiT for its subjectuniqueidentifierurl, by checking if there is a DNS entry using the peer’s RODiT token\_id that follows the format _SMARTCONTRACTID.smartcontract.subjectuniqueidentifierurl_. If the entry does not exists, the smart contract has been revoked. The reference implementation uses the function _pub fn verify\_rodit\_smartcontract\_istrusted_ for this check. (Note: Do we need to check if the RODiT root is Live and Active) 6. Valid: The endpoint may check optional properties of the RODiT, like location, number of transactions per minute, among other use cases. Reference Implementation - Minimum Viable Interface From ae4634af24c78fbefdccd443b0a2452bcd828349 Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:15:38 +0200 Subject: [PATCH 09/20] Update nep-0509.md --- neps/nep-0509.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 0c456bb05..91732bcf1 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -111,26 +111,6 @@ export class TokenMetadata { } ``` -A new attribute MUST be added to each `Token` struct: - -```java - export class Token { - owner_id: string; - approved_account_ids: { [accountId: string]: number }; - next_approval_id: number; - - constructor({ - ownerId, - approvedAccountIds, - nextApprovalId, - }: { - ownerId: string; - approvedAccountIds: { [accountId: string]: number }; - nextApprovalId: number; - }) -} -``` - Service Provider root RODiT --------------------------- From 39a7aa6fd9998c15eacf4812594ac18de68f84af Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:17:40 +0200 Subject: [PATCH 10/20] Update nep-0509.md --- neps/nep-0509.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index 91732bcf1..aa84979ee 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -143,7 +143,7 @@ Service Provider server and client RODiT Handling of RODiT ----------------- -The reference implementation of RODiT uses implicit accounts ([https://docs.near.org/integrator/implicit-accounts](https://docs.near.org/integrator/implicit-accounts) ). Upon creation, RODiT can be sent to final addresses or to an address from where RODiT can be distributed to final endpoint addresses. Practitioners can use NEAR CLI or NEAR CLI RS to view the content of a RODiT or send it to an address. The reference implementation uses a bash script to make handling the RODiT sets more user friendly. It can be found here: [https://github.com/alanesmizi/cgwallet](https://github.com/alanesmizi/cgwallet) +The reference implementation of RODiT uses implicit accounts ([https://docs.near.org/integrator/implicit-accounts](https://docs.near.org/integrator/implicit-accounts) ). Upon creation, RODiT can be sent to final addresses or to an address from where RODiT can be distributed to final endpoint addresses. Practitioners can use NEAR CLI or NEAR CLI RS to view the content of a RODiT or send it to an address. The reference implementation uses a bash script to make handling the RODiT sets more user friendly. It can be found here: [https://github.com/cableguard/cgroditvpn](https://github.com/cableguard/cgroditvpn) The script has the following options: * cgroditwallet.sh: List of available accounts From 58f2b25daec5a9870ba8a1d6788c9312c4952b8e Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:19:08 +0200 Subject: [PATCH 11/20] Update nep-0509.md --- neps/nep-0509.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index aa84979ee..a78d41364 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -163,7 +163,7 @@ RODiT authentication is always mutual. The order for the checks and exchange pro Both endpoints check that the peer can pass the following checks: -1. Possession: The endpoint signs the token\_id (somehow equivalent to CertificateVerify in X.509) with the private key of the RODiT address, sends the token\_id and the signature to the peer. Upon reception the peer fetches from the blockchain the public key where the token\_id is, and checks the signature. (Notes: There is not certificate request as when using digital certificates) **Do I need to add the SMARTCONTRACTID to the handshake?** The reference implementation uses the function _pub fn verify\_hasrodit\_getit_ for this check. +1. Possession: The endpoint signs the token\_id (somehow equivalent to CertificateVerify in X.509) with the private key of the RODiT address, sends the token\_id and the signature to the peer. Upon reception the peer fetches from the blockchain the public key where the token\_id is, and checks the signature. (Notes: There is not certificate request as when using digital certificates) The reference implementation uses the function _pub fn verify\_hasrodit\_getit_ for this check. 2. Genuine: The endpoint fetches from the blockchain the public key where the serviceprovider\_id of the own RODiT is, and checks the serviceprovider\_signature against the peer’s RODiT token\_id and the fetched public key. The reference implementation uses the function _pub fn verify\_rodit\_isamatch_ for this check. 3. Live: The endpoint checks the current time and date against the not\_after and not\_before fields of the peer’s RODiT. The reference implementation uses the function _pub fn verify\_rodit\_islive_ for this check. 4. Active: The endpoint checks if there is a DNS entry using the peer’s RODiT token\_id that follows the format _token\_id.revoked.subjectuniqueidentifierurl_. If the entry exists, the RODiT has been revoked. The reference implementation uses the function _pub fn verify\_rodit\_isactive_ for this check. From 9d7fbf588ee1a9ee9d14f4e4e0e871fb476bb4da Mon Sep 17 00:00:00 2001 From: Cableguard RODiT <154883089+cableguard@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:44:43 +0200 Subject: [PATCH 12/20] Update nep-0509.md --- neps/nep-0509.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/neps/nep-0509.md b/neps/nep-0509.md index a78d41364..0476b99bf 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0509.md @@ -201,16 +201,21 @@ RODiT could be used as personal user accounts not connected to any directory, wi * **phonenumber**: Contact phone number * **postaddress**: Contact address in plus code format -RODiT can also be used for SSH authentication and API authentication. +RODiT can also hs the potential to be used for SSH authentication and API authentication. +Using RODiT can lead to new commercialization practices by Service Providers as they can delegate sales and distribution to third parties and resellers easily, by providing stocks of RODiT. Consequences ------------ ### Positive -* consequence +* Reducing complexity and costs by consolidating authentication, configuration, and licensing of online services into a single token +* Preventing rogue credential issuers through a verifiable trust model +* Enabling seamless issuing and secure delivery of credentials to endpoints +* Allowing independent key rotation decoupled from license expiration +* Robust mutual authentication and protection against man-in-the-middle attacks ### Negative -* consequence +* The current implementation does not include mechanism to encrypt the information stored in the RODiT, so it can only store information that can be made public without consequence. ### Backwards Compatibility There is no need to backwards compatibility as RODiT have a use case fundamentally different from Non-fungible tokens. From cc10716f18a149435885f6179cfc81f3e301b7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 13:54:05 +0000 Subject: [PATCH 13/20] nep519 --- neps/{nep-0509.md => nep-0519.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename neps/{nep-0509.md => nep-0519.md} (99%) diff --git a/neps/nep-0509.md b/neps/nep-0519.md similarity index 99% rename from neps/nep-0509.md rename to neps/nep-0519.md index 0ab6279b1..180582a3d 100644 --- a/neps/nep-0509.md +++ b/neps/nep-0519.md @@ -1,5 +1,5 @@ --- -NEP: 509 +NEP: 519 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal Status: New @@ -83,7 +83,7 @@ Version Number that indicates that a the contract adheres to the current version Version Number - | + | 509 String @@ -160,7 +160,7 @@ String | -NEP509 +NEP519 | From 809e23d91613803279afde4c862cf976ed528d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 14:06:04 +0000 Subject: [PATCH 14/20] typos --- neps/nep529.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neps/nep529.md b/neps/nep529.md index c4cbb1e46..26ac6e011 100644 --- a/neps/nep529.md +++ b/neps/nep529.md @@ -1,5 +1,5 @@ --- -NEP: 529 +NEP: 519 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal Status: New @@ -53,7 +53,7 @@ An implementing contract MUST include the following fields on-chain: | **versionnumber** (**NFT\_METADATA\_SPEC**) | Version Number that indicates that a the contract adheres to the current versions of this spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. | Version Number | String | RODiT-near.org-MM.nn.rr , MM: Major version , nn: Minor version , rr: revision , where M, m and r are decimal digits. | | **symbol** | Symbol | Not Applicable | String | default value when implementing this standard without custom fields: RODiT | | **base\_uri** | Smart Contract ID, serves as identification of the Issuer | Issuer Unique Identifier | URL to guarantee it is unique and controlled by a single entity | URL | -| **NFT\_STANDARD\_NAME** | Smart Contract Standard | No equivalent | String | NEP529 | +| **NFT\_STANDARD\_NAME** | Smart Contract Standard | No equivalent | String | NEP509 | For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] @@ -201,7 +201,7 @@ RODiT could be used as personal user accounts not connected to any directory, wi * **phonenumber**: Contact phone number * **postaddress**: Contact address in plus code format -RODiT can also hs the potential to be used for SSH authentication and API authentication. +RODiT can also the potential to be used for SSH authentication and API authentication. Using RODiT can lead to new commercialization practices by Service Providers as they can delegate sales and distribution to third parties and resellers easily, by providing stocks of RODiT. Consequences From 1ed5363e20893fb95fadc5aecb16a16b0cdb0626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 14:14:28 +0000 Subject: [PATCH 15/20] mvi --- neps/nep529.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/neps/nep529.md b/neps/nep529.md index 26ac6e011..cc4108b30 100644 --- a/neps/nep529.md +++ b/neps/nep529.md @@ -173,9 +173,27 @@ Both endpoints check that the peer can pass the following checks: Reference Implementation - Minimum Viable Interface --------------------------------------------------- -traits and structs for rust +https://github.com/cableguard/cgtun/blob/49d01c29c656e2f34c6dc2bca67e375f9bbf8f09/cableguard/src/noise/mod.rs#L1166 -interfaces and classes for java script +pub fn verify_hasrodit_getit( + rodit_id: [u8;RODIT_ID_SZ], + rodit_id_signature: [u8;RODIT_ID_SIGNATURE_SZ], + +pub fn verify_rodit_isamatch( + own_serviceproviderid: String, + peer_serviceprovidersignature: String, + peer_token_id: [u8;RODIT_ID_SZ], + +pub fn verify_rodit_islive( + peer_rodit_notafter: String, + peer_rodit_notbefore: String, + +pub fn verify_rodit_isactive( + token_id: String, + own_subjectuniqueidentifierurl: String, + +pub fn verify_rodit_smartcontract_istrusted( + own_subjectuniqueidentifierurl: String, Security Implications --------------------- From 7b421007004ff7c26330c86c44e34a5f89880399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 14:16:43 +0000 Subject: [PATCH 16/20] renamed --- neps/{nep529.md => nep-0529.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename neps/{nep529.md => nep-0529.md} (100%) diff --git a/neps/nep529.md b/neps/nep-0529.md similarity index 100% rename from neps/nep529.md rename to neps/nep-0529.md From 5eeccf22b6c16fd71748bebf2761571f39767a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 14:18:27 +0000 Subject: [PATCH 17/20] typos --- neps/nep-0529.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0529.md b/neps/nep-0529.md index cc4108b30..b42a9e5b3 100644 --- a/neps/nep-0529.md +++ b/neps/nep-0529.md @@ -1,8 +1,8 @@ --- -NEP: 519 +NEP: 529 Title: Rich Online Digital Token Authors: Vicente Aceituno Canal -Status: New +Status: Draft DiscussionsTo: https://github.com/nearprotocol/neps/pull/529 Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates Version: 1.0.0 From b9b84496082981631d0eff71ad6be3789c9c6c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Fri, 21 Jun 2024 14:20:03 +0000 Subject: [PATCH 18/20] added 529 to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ac517436..0f76cf230 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement | [0452](https://github.com/near/NEPs/blob/master/neps/nep-0452.md) | Linkdrop Standard | @benkurrek @miyachi | Final | | [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | | [0514](https://github.com/near/NEPs/blob/master/neps/nep-0514.md) | Fewer Block Producer Seats in `testnet` | @nikurt | Final | +| [0529](https://github.com/near/NEPs/blob/master/neps/nep-0529.md) | Rich Online Digital Tokens spec | @cableguard | Draft | ## Specification From 3fdf7e8c018074f851ed8b07d05f281a6c5739af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Sat, 22 Jun 2024 11:23:25 +0000 Subject: [PATCH 19/20] reviewed --- neps/nep-0529.md | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/neps/nep-0529.md b/neps/nep-0529.md index b42a9e5b3..642b46497 100644 --- a/neps/nep-0529.md +++ b/neps/nep-0529.md @@ -1,17 +1,17 @@ --- NEP: 529 -Title: Rich Online Digital Token +Title: Rich Online Digital Tokens Authors: Vicente Aceituno Canal Status: Draft DiscussionsTo: https://github.com/nearprotocol/neps/pull/529 -Type: Extensible Non fungible token (Rich Online Digital Token) akin to X.509 digital certificates +Type: Extensible Non fungible token (Rich Online Digital Token) akin to digital certificates Version: 1.0.0 Created: 2024-06-21 LastUpdated: 2024-06-21 --- ## Summary -Properly designed custom non-fungible-tokens can complement or replace X.509 digital certificates for most purposes. The design presented in this NEP can be easily extended for any number of use cases that use digital certificates. among them, mutual authentication, electronic mail, digital signing and time stamping. +Properly designed custom non-fungible-tokens (RODiT) can complement or replace digital certificates for most purposes. The design presented in this NEP can be easily extended for any number of use cases that use digital certificates. among them, mutual authentication, electronic mail, digital signing, code signing and time stamping. ## Motivation Public Key Infrastructure is a prevalent way to use public key encryption. The original motivation of this NEP proposal are the many flaws in Public Key Infrastructure. It is beyond the scope of this NEP to explain these flaws in detail, please refer to the sources \[1\]\[2\]\[3\]\[4\]. @@ -23,17 +23,16 @@ Currently there are no other NEP specifications covering this specific use case. Problems solved --------------- In this document we call the custom non-fungible-tokens used Rich Online Digital Tokens (RODiT for short). The problems solved are the following: -1. When implementing mutual authentication with X.509 digital certificates, the workflow has several steps, one of them requires transferring a file (CSR) between the endpoint and the CA. With RODiT we use a workflow with fewer steps, without file transfer, that is completed when the RODiT is sent (not installed), to a blockchain address. The impact of using a simpler process becomes highly significant as the number of participant nodes grows. -2. With X.509 digital certificates, key rotation requires issuing and installing a new digital certificate when the key is due to be rotated, regardless of the expiration date of the service being secured with the digital certificate. With RODiT, key rotation is decoupled from service expiration, as it does not require issuing a new RODiT. Key rotation using RODiT can be performed independently for every node, without any coordination between the parties, greatly simplifying the management of key rotation. -3. Rogue Certificate Authorities (Issuers in X.509 terminology) can generate digital certificates to any identifier, despite of Certificate Transparency and CAA records, making key pinning necessary in high security scenarios. Any X.509 Issuer can create a digital certificate for any domain name, while the legitimate owner of the domain name may not be aware it has been issued. While RODiT are based on smart contracts controlled by Issuers, it is the Service Providers that issue and revoke RODiT for the identifiers they control, and the Service Provider has the exclusive prerogative to authorize the smart contract. This prevents Unexpected Certificates as described in \[5\], making key pinning unnecessary. This NEP describes a mechanism for domain names use by service providers to declare what issuers are trusted to issue valid digital certificates for them, removing this threat. +1. When implementing mutual authentication with X.509 digital certificates, the workflow has several steps, one of them requires transferring a file (CSR) between the endpoint and the CA. When using SSH digital certificates, the workflow has several steps, one of them requires registering the trusted public key in a registry of authorized keys. With RODiT we use a workflow with fewer steps, without file transfer, that is completed when the RODiT is sent (not installed), to a blockchain address. The impact of using a simpler process becomes highly significant as the number of participant endpoints grows. +2. With X.509 digital certificates, key rotation requires coordinated issuing and installing of new digital certificates when the key is due to be rotated, regardless of the expiration date of the service being secured with the digital certificate. SSH digital certificates expiration also require coordination across endpoints. With RODiT, key rotation is decoupled from service expiration, as it does not require issuing a new RODiT. Key rotation using RODiT can be performed independently for every endpoint, without any coordination between the parties, greatly simplifying the management of key rotation. +3. Rogue Certificate Authorities (Issuers in X.509 terminology) can generate digital certificates to any identifier, despite of Certificate Transparency and CAA records, making key pinning necessary in high security scenarios. Any X.509 Issuer can create a digital certificate for any domain name, while the legitimate owner of the domain name may not be aware it has been issued. While RODiT are based on smart contracts controlled by Issuers, it is the Service Providers that issue and revoke RODiT for the identifiers they control, and the Service Provider has the exclusive prerogative to authorize the smart contract. This prevents Unexpected Certificates as described in \[5\], making key pinning or Certificate Transparency unnecessary. This NEP describes a mechanism for domain names use by service providers to declare what Issuers are trusted to issue valid digital certificates for them, removing this threat. Potential use cases ------------------- -Rich Online Digital Tokens can be used as a complement or replacement of digital certificates for VPN authentication (reference implementation), SSH authentication and API authentication, among others. +Rich Online Digital Tokens can be used as a complement or replacement of digital certificates for VPN authentication (reference implementation at [https://github.com/cableguard]), SSH authentication and API authentication, among others. ## Scope This NEP includes RODiT structure with mandatory and optional fields. It does not include: - * Governance of RODiT, who can create RODiT issuing smart contracts and how is their reputation determined. * How RODiT field values are validated to be accurate, particularly when a field is an identifier or an address. * How wallets interact via IPC or other mechanisms with applications using RODiT. @@ -41,8 +40,8 @@ This NEP includes RODiT structure with mandatory and optional fields. It does no ## Terminology Some terms are used with a specific meaning, as follows: * **Rich Online Digital Token**: Abbreviated as RODiT, is a non fungible token which lifecycle and structure is conformant with this document. -* **Issuer**: The organization that creates a smart contract that is used by the Service Providers to mint their RODiT. * **Service Provider**: Organization that signs its RODiT digitally and provides a service to users where RODiT are used for mutual authentication. +* **Issuer**: The organization that creates a smart contract that is used by the Service Providers to mint their RODiT. * **Holder**: A person or system that controls a RODiT via a key pair in a cryptographic wallet. ## Specification @@ -111,7 +110,7 @@ export class TokenMetadata { } ``` -Service Provider root RODiT +Service Provider root RODiT format --------------------------- | **Field Name** | **Default value and Valid Range** | @@ -125,7 +124,7 @@ Service Provider root RODiT | **serviceprovider\_id** | ULIDOFTHESERVICEPROVIDER | | **serviceprovider\_signature** | SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT (this RODiT) is sent upon creation | -Service Provider server and client RODiT +Service Provider server and client RODiT format ---------------------------------------- | **Field Name** | **Default value and Valid Range** | @@ -158,7 +157,6 @@ The key pair used for encryption can be rotated by sending the RODiT to a new ad Authentication with RODiT ------------------------- - RODiT authentication is always mutual. The order for the checks and exchange protocol in the reference implementation uses the NOISE protocol (See [https://noiseprotocol.org/](https://noiseprotocol.org/)), as implemented in Wireguard ([https://www.wireguard.com/papers/wireguard.pdf](https://www.wireguard.com/papers/wireguard.pdf)), with the following steps: Initiation, Response and Confirmation. Both endpoints check that the peer can pass the following checks: @@ -172,7 +170,6 @@ Both endpoints check that the peer can pass the following checks: Reference Implementation - Minimum Viable Interface --------------------------------------------------- - https://github.com/cableguard/cgtun/blob/49d01c29c656e2f34c6dc2bca67e375f9bbf8f09/cableguard/src/noise/mod.rs#L1166 pub fn verify_hasrodit_getit( @@ -199,15 +196,17 @@ Security Implications --------------------- RODiT offer robust security features, including: * Mutual authentication by default. -* Explicit authorization of Issuers preventing person in the middle attacks. +* Explicit authorization of Issuers preventing man in the middle attacks. * Easy detection and recovery from key compromise. As the RODiT is associated with a blockchain address, the only way the attacker can keep exclusive control of the RODiT is moving it to a new address. This can be observed publicly as soon as it happens. Besides, as RODiT can only be verified online, so all parties will react immediately to the RODiT being revoked an will not accept it. Man in the middle attacks are far more challenging using RODiT than X.509 certificates, as we can verify validity against multiple RPC providers or even have our own local NEAR node. Alternatives ------------ -RODiT have been developed as an alternative to X.509 digital certificates. +RODiT have been developed as an alternative to X.509 and SSH digital certificates. Future possibilities -------------------- +* RODiT could be used for SSH authentication and API authentication. +* Using RODiT can lead to new commercialization practices by Service Providers as they can delegate sales and distribution to third parties and resellers easily, by providing stocks of RODiT. RODiT could be used as personal user accounts not connected to any directory, with fields like: * **locationofbirth**: Place of birth in plus code format @@ -219,12 +218,8 @@ RODiT could be used as personal user accounts not connected to any directory, wi * **phonenumber**: Contact phone number * **postaddress**: Contact address in plus code format -RODiT can also the potential to be used for SSH authentication and API authentication. -Using RODiT can lead to new commercialization practices by Service Providers as they can delegate sales and distribution to third parties and resellers easily, by providing stocks of RODiT. - Consequences ------------ - ### Positive * Reducing complexity and costs by consolidating authentication, configuration, and licensing of online services into a single token * Preventing rogue credential issuers through a verifiable trust model @@ -240,8 +235,7 @@ There is no need to backwards compatibility as RODiT have a use case fundamental Unresolved Issues (Optional) ---------------------------- - -RODiT use implicit accounts at the moment due to cryptographic wallets missing any kind of interface with other software, for example browsers. The utility of RODiT will be limited to technical use cases until an interface is developed. +RODiT use implicit accounts at the moment due to cryptographic wallets missing any kind of interface with other software, for example browsers. The utility of RODiT will be limited to use cases that are compatible with implicit accounts until an interface is developed. Changelog --------- From 4be93f3ebd118f036b5b88415a4a13789e454056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Ccableguard=40cableguard=2Eorg=E2=80=9D?= <“cableguard@cableguard.org”> Date: Sun, 30 Jun 2024 10:37:54 +0000 Subject: [PATCH 20/20] lint fixed --- neps/nep-0529.md | 75 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/neps/nep-0529.md b/neps/nep-0529.md index 642b46497..a9543c873 100644 --- a/neps/nep-0529.md +++ b/neps/nep-0529.md @@ -11,9 +11,11 @@ LastUpdated: 2024-06-21 --- ## Summary + Properly designed custom non-fungible-tokens (RODiT) can complement or replace digital certificates for most purposes. The design presented in this NEP can be easily extended for any number of use cases that use digital certificates. among them, mutual authentication, electronic mail, digital signing, code signing and time stamping. ## Motivation + Public Key Infrastructure is a prevalent way to use public key encryption. The original motivation of this NEP proposal are the many flaws in Public Key Infrastructure. It is beyond the scope of this NEP to explain these flaws in detail, please refer to the sources \[1\]\[2\]\[3\]\[4\]. Using blockchain issued tokens equivalent to digital certificates can provide better functionality than traditional digital certificates without compromising security. @@ -21,30 +23,40 @@ Using blockchain issued tokens equivalent to digital certificates can provide be Currently there are no other NEP specifications covering this specific use case. Problems solved + --------------- + In this document we call the custom non-fungible-tokens used Rich Online Digital Tokens (RODiT for short). The problems solved are the following: + 1. When implementing mutual authentication with X.509 digital certificates, the workflow has several steps, one of them requires transferring a file (CSR) between the endpoint and the CA. When using SSH digital certificates, the workflow has several steps, one of them requires registering the trusted public key in a registry of authorized keys. With RODiT we use a workflow with fewer steps, without file transfer, that is completed when the RODiT is sent (not installed), to a blockchain address. The impact of using a simpler process becomes highly significant as the number of participant endpoints grows. 2. With X.509 digital certificates, key rotation requires coordinated issuing and installing of new digital certificates when the key is due to be rotated, regardless of the expiration date of the service being secured with the digital certificate. SSH digital certificates expiration also require coordination across endpoints. With RODiT, key rotation is decoupled from service expiration, as it does not require issuing a new RODiT. Key rotation using RODiT can be performed independently for every endpoint, without any coordination between the parties, greatly simplifying the management of key rotation. 3. Rogue Certificate Authorities (Issuers in X.509 terminology) can generate digital certificates to any identifier, despite of Certificate Transparency and CAA records, making key pinning necessary in high security scenarios. Any X.509 Issuer can create a digital certificate for any domain name, while the legitimate owner of the domain name may not be aware it has been issued. While RODiT are based on smart contracts controlled by Issuers, it is the Service Providers that issue and revoke RODiT for the identifiers they control, and the Service Provider has the exclusive prerogative to authorize the smart contract. This prevents Unexpected Certificates as described in \[5\], making key pinning or Certificate Transparency unnecessary. This NEP describes a mechanism for domain names use by service providers to declare what Issuers are trusted to issue valid digital certificates for them, removing this threat. Potential use cases -------------------- -Rich Online Digital Tokens can be used as a complement or replacement of digital certificates for VPN authentication (reference implementation at [https://github.com/cableguard]), SSH authentication and API authentication, among others. + +-------------------; + +Rich Online Digital Tokens can be used as a complement or replacement of digital certificates for VPN authentication (reference implementation at [https://github.com/cableguard]), SSH authentication and API authentication, among others.NEPs ## Scope + This NEP includes RODiT structure with mandatory and optional fields. It does not include: + * Governance of RODiT, who can create RODiT issuing smart contracts and how is their reputation determined. * How RODiT field values are validated to be accurate, particularly when a field is an identifier or an address. * How wallets interact via IPC or other mechanisms with applications using RODiT. ## Terminology + Some terms are used with a specific meaning, as follows: + * **Rich Online Digital Token**: Abbreviated as RODiT, is a non fungible token which lifecycle and structure is conformant with this document. * **Service Provider**: Organization that signs its RODiT digitally and provides a service to users where RODiT are used for mutual authentication. * **Issuer**: The organization that creates a smart contract that is used by the Service Providers to mint their RODiT. * **Holder**: A person or system that controls a RODiT via a key pair in a cryptographic wallet. ## Specification + An implementing contract MUST include the following fields on-chain: | **Field Name** | **Description** | **X.509 Equivalent** | **Type and Format** | **Default value and Valid Range** | @@ -57,6 +69,7 @@ An implementing contract MUST include the following fields on-chain: For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] Note: + * MODIFIEDBASE\_URI is base\_uri, replacing the dot separating the TLD with the rest of the domain name with a dash “-”. * SMARTCONTRACTID follows the following format: MMNNrr-MODIFIEDBASE\_URI.org @@ -89,6 +102,7 @@ The following X.509 fields are not implemented as part of RODiT by default, but For sample implementation of custom fields see (examples with the fields cidrblock, listenport, dns, allowedips): For sample implementation see: [https://github.com/cableguard/cgforge/blob/mainnet/contract/src/metadata.ts] ## Interface + Metadata applies at both the contract level (`RoditContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: ```java @@ -111,7 +125,8 @@ export class TokenMetadata { ``` Service Provider root RODiT format ---------------------------- + +---------------------------; | **Field Name** | **Default value and Valid Range** | | --- | --- | @@ -125,7 +140,8 @@ Service Provider root RODiT format | **serviceprovider\_signature** | SHA384WITHECDSA signature of the token\_id with private key of the blockchain address where the Service Provider root RODiT (this RODiT) is sent upon creation | Service Provider server and client RODiT format ----------------------------------------- + +----------------------------------------; | **Field Name** | **Default value and Valid Range** | | --- | --- | @@ -140,11 +156,13 @@ Service Provider server and client RODiT format Handling of RODiT ------------------ + +-----------------; The reference implementation of RODiT uses implicit accounts ([https://docs.near.org/integrator/implicit-accounts](https://docs.near.org/integrator/implicit-accounts) ). Upon creation, RODiT can be sent to final addresses or to an address from where RODiT can be distributed to final endpoint addresses. Practitioners can use NEAR CLI or NEAR CLI RS to view the content of a RODiT or send it to an address. The reference implementation uses a bash script to make handling the RODiT sets more user friendly. It can be found here: [https://github.com/cableguard/cgroditvpn](https://github.com/cableguard/cgroditvpn) The script has the following options: + * cgroditwallet.sh: List of available accounts * cgroditwallet.sh _accountID_: Lists the RODiT Ids in the account and its balance * cgroditwallet.sh _accountID_ keys: Displays the accountID and the Private Key of the account @@ -156,7 +174,9 @@ The script has the following options: The key pair used for encryption can be rotated by sending the RODiT to a new address. Authentication with RODiT -------------------------- + +-------------------------; + RODiT authentication is always mutual. The order for the checks and exchange protocol in the reference implementation uses the NOISE protocol (See [https://noiseprotocol.org/](https://noiseprotocol.org/)), as implemented in Wireguard ([https://www.wireguard.com/papers/wireguard.pdf](https://www.wireguard.com/papers/wireguard.pdf)), with the following steps: Initiation, Response and Confirmation. Both endpoints check that the peer can pass the following checks: @@ -169,7 +189,9 @@ Both endpoints check that the peer can pass the following checks: 6. Valid: The endpoint may check optional properties of the RODiT, like location, number of transactions per minute, among other use cases. Reference Implementation - Minimum Viable Interface ---------------------------------------------------- + +---------------------------------------------------; + https://github.com/cableguard/cgtun/blob/49d01c29c656e2f34c6dc2bca67e375f9bbf8f09/cableguard/src/noise/mod.rs#L1166 pub fn verify_hasrodit_getit( @@ -193,22 +215,30 @@ pub fn verify_rodit_smartcontract_istrusted( own_subjectuniqueidentifierurl: String, Security Implications ---------------------- + +---------------------; + RODiT offer robust security features, including: + * Mutual authentication by default. * Explicit authorization of Issuers preventing man in the middle attacks. * Easy detection and recovery from key compromise. As the RODiT is associated with a blockchain address, the only way the attacker can keep exclusive control of the RODiT is moving it to a new address. This can be observed publicly as soon as it happens. Besides, as RODiT can only be verified online, so all parties will react immediately to the RODiT being revoked an will not accept it. Man in the middle attacks are far more challenging using RODiT than X.509 certificates, as we can verify validity against multiple RPC providers or even have our own local NEAR node. Alternatives ------------- + +------------; + RODiT have been developed as an alternative to X.509 and SSH digital certificates. Future possibilities --------------------- + +--------------------; + * RODiT could be used for SSH authentication and API authentication. * Using RODiT can lead to new commercialization practices by Service Providers as they can delegate sales and distribution to third parties and resellers easily, by providing stocks of RODiT. RODiT could be used as personal user accounts not connected to any directory, with fields like: + * **locationofbirth**: Place of birth in plus code format * **dateandtimeofbirth**: Date and time of birth in GeneralizedTime format or RFC3339 * **namesshared**: Part of the full name shared with family (this is known as surname in some countries) @@ -219,8 +249,11 @@ RODiT could be used as personal user accounts not connected to any directory, wi * **postaddress**: Contact address in plus code format Consequences ------------- + +------------; + ### Positive + * Reducing complexity and costs by consolidating authentication, configuration, and licensing of online services into a single token * Preventing rogue credential issuers through a verifiable trust model * Enabling seamless issuing and secure delivery of credentials to endpoints @@ -228,21 +261,28 @@ Consequences * Robust mutual authentication and protection against man-in-the-middle attacks ### Negative + * The current implementation does not include mechanism to encrypt the information stored in the RODiT, so it can only store information that can be made public without consequence. ### Backwards Compatibility + There is no need to backwards compatibility as RODiT have a use case fundamentally different from Non-fungible tokens. Unresolved Issues (Optional) ----------------------------- + +----------------------------; + RODiT use implicit accounts at the moment due to cryptographic wallets missing any kind of interface with other software, for example browsers. The utility of RODiT will be limited to use cases that are compatible with implicit accounts until an interface is developed. Changelog ---------- + +---------; + Version 1.0.0 Submitted for approval References ----------- + +----------; 1. [https://www.schneier.com/wp-content/uploads/2016/02/paper-pki.pdf](https://www.schneier.com/wp-content/uploads/2016/02/paper-pki.pdf) @@ -256,10 +296,13 @@ References ### 1.0.0 - Initial Version + > Placeholder for the context about when and who approved this NEP version. #### Benefits + > List of benefits filled by the Subject Matter Experts while reviewing this version: + * Benefit 1 * Benefit 2 @@ -273,5 +316,7 @@ References | 2 | | | | Copyright ---------- + +---------; + Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).