Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - WebOfTrust/cesride: Cryptographic primitives for Composable Event Streaming Representation (CESR) · GitHub
Skip to content

Repository files navigation

cesride

cesridecodecov

Cryptographic primitives for use with Composable Event Streaming Representation (CESR).

This library is currently under construction. If you want to help build, see contributing below.

Important Reference Material

Contributing

If you want to contribute, check out the issues. Tags provide some guidance.

When starting a new issue, ensure there are no others working on the same thing to avoid duplicated effort (although alternative implementations are always welcome and considered):

  • check that there is no open pull request
  • make sure no one has assigned themselves
  • look for comments on the issue
  • look for development integrations ('linked an issue that may be closed by this pull request')

When you find an issue you want to take on:

  • make yourself an assignee, if possible
  • open a Pull Request against a branch you created against your fork - even if empty
  • paste a link to the PR in a comment on the issue you are working on for visibility

For better coordination, join the #cesr-dev slack channel using the link at the bottom of this document.

Development

Install dependencies:

cargo install cargo-audit
cargo install cargo-tarpaulin

Change some code and then fix it automatically:

make fix

Commit your changes locally, and run these automated tests (requires brew install wasm-pack):

make clean preflight

You are now ready to open a pull request!

Terminology

cesride is built from cryptographic primitives that are named clearly and concisely. That said, those unfamiliar with the naming strategy but familiar with cryptography may find themselves a bit lost when first working with cesride. Implementation was ported from KERIpy and terminology was carried along with the code. The basics:

  • Diger - a primitive that represents a digest. It has the ability to verify that an input hashes to its raw value.
  • Verfer - a primitive that represents a public key. It has the ability to verify signatures on data.
  • Signer - a primitive that represents a private key. It has the ability to create Sigers and Cigars (signatures).
  • Siger - an indexed signature. This is used within KERI when there are multiple current keys associated with an identifier.
  • Cigar - an unindexed signature.
  • Salter - a primitive that represents a seed. It has the ability to generate new Signers.

Each primitive will have methods attached to it that permit one to generate and parse the qualified base2 or base64 representation. Common methods you'll find:

  • .qb64() - qualified base-64 representation of cryptographic material as a string
  • .qb64b() - qualified base-64 representation of cryptographic material as octets (bytes)
  • .qb2() - qualified base-2 representation of cryptographic material as octets (bytes)
  • .code() - qualifying code (describes the type of cryptographic material)
  • .raw() - raw cryptographic material (unqualified) as octets (bytes)

Qualification

Q: What do you mean, qualified cryptographic material?

A: There are tables of codes similar to a TLV table but omitting the length field for almost all cases (as the primitives are fixed in size). The type or code, in CESR vernacular, conveys enough information to allow the application to parse data with qualified cryptographic material embedded in it.

Here is what we mean:

DKxy2sgzfplyr-tgwIxS19f2OchFHtLwPWD3v4oYimBx - this is prefixed with a D. If we look that code up in the table linked in the answer above, we find this is a transferable (rotatable) Ed25519 public key.

ELEjyRTtmfyp4VpTBTkv_b6KONMS1V8-EW-aGJ5P_QMo - this is prefixed with an E. Again, consulting the table, we learn this is a Blake3 256 digest.

Each primitive can be represented in Base64 or binary, and can be processed from either format.

Examples

use cesride::{common::Tierage,Salter};// in this example we sign some data and ensure the signature verifieslet authentic = b"abcdefg";let forgery = b"abcdefgh";letmut sigers:Vec<Siger> = vec![];// delay creating sensitive material until the last moment so it is resident in memory for shorterlet salter = Salter::new_with_defaults(Some(Tierage::med))?;// generate a set of 3 signing keys. the fourth argument here is the code, and when we specify// none we'll be given an Ed25519 key. the path here (third argument) will be input during key// stretching so that the same seed can be used for a number of keys with differing pathslet signers = salter.signers(Some(3),None,Some("my-key"),None,None,None,None)?;// sign some datafor i in0..signers.len(){
sigers.push(signers[i].sign_indexed(authentic,false, i asu32,None)?);}// verify the signaturesfor i in0..signers.len(){// check that verification works if the data and signature matchassert!(signers[i].verfer().verify(&sigers[i].raw(), authentic)?);// verification fails if the data (or signature) does not matchassert!(!signers[i].verfer().verify(&sigers[i].raw(), forgery)?);}
use cesride::{Signer,Indexer,Matter};// here we verify that a cigar primitive and a siger primitive have the same underlying// cryptographic materiallet data = b"abcdefg";// defaults to Ed25519let signer = Signer::new_with_defaults(None,None)?;// create our signatureslet cigar = signer.sign_unindexed(data)?;let siger = signer.sign_indexed(data,false,0,None)?;// compare the raw signaturesassert_eq!(cigar.raw(), siger.raw());
use cesride::{Diger,Matter, matter};// here we simply print a qualified digest in base64 to stdout after hashing serialized data// hash digests underpin core concepts of the KERI ecosystemlet data = b"abcdefg";// derive the digest, opting this time to specify the algorithmlet diger = Diger::new_with_ser(data,Some(matter::Codex::SHA3_512))?;// output the digestprintln!("Blake3 256 digest: #{d}", d=diger.qb64()?);

For more implementation details at this time, see KERIpy.

Entropy

We use two OsRng implementations to obtain our random data. Our private keys are sometimes generated from stock methods in the underlying libraries, which is why we currently include both implementations (the two signing modules depend on traits that are incompatible).

When using Salter, one can produce many deterministic and reproducible results (such as keys) from the same seed material, or use random seed material. In the latter case, we use the more recent of the OsRng implementations directly to fill buffers.

External Dependencies (crates)

Key Stretching

  • Argon2 (argon2) - Salter uses argon2id to stretch seeds into keying material. These are our security tiers and param choices, which maintain compatiblity with the reference python implementation (KERIpy):
    • min: unavailable outside the cesride context except when passing the temp param directly to stretch() to perform manual stretching. NEVER use this security tier in production. argon2id params:
      • m: 8
      • t: 1
      • p: 1
    • low: the default tier, suitable for low-risk online interactions
      • m: 65536
      • t: 2
      • p: 1
    • med: suitable for high-risk online interactions
      • m: 262144
      • t: 3
      • p: 1
    • high: resitant to offline attacks (use this for backups)
      • m: 1048576
      • t: 4
      • p: 1

We use 16 bytes of entropy from OsRng in rand_core to seed argon2. For more details on selecting appropriate argon2 parameters, consult this document.

Hashing

cesride supports the following hash algorithms:

Blake3 is recommended for most applications since it outperforms the other algorithms.

Signing

cesride supports the following signing algorithms:

We have planned support for Ed448.

The ECDSA curves (Secp256k1 and Secp256r1) use randomized signatures. Ed25519 is always deterministic. This means that if you need to avoid correlation and want to use Ed25519, you'll need to salt your data for every use case that you do not want correlated. ACDC, for example, takes this into account, allowing for configurable use of Ed25519 by injecting salty nonces in the data to be signed where privacy is a concern.

Community

Bi-weekly Meeting

Information here

Discord

About

Cryptographic primitives for Composable Event Streaming Representation (CESR)

Topics

Resources

Stars

19 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages