Gathering detailed insights and metrics for dag-jose
Gathering detailed insights and metrics for dag-jose
Gathering detailed insights and metrics for dag-jose
Gathering detailed insights and metrics for dag-jose
dag-jose-utils
Utility functions for the dag-jose ipld codec
@ceramicnetwork/ipfs-daemon
IPFS daemon wraps js-ipfs instance with dag-jose codec enabled
@dustil/ipfs-daemon
IPFS daemon wraps js-ipfs instance with dag-jose codec enabled
@cambrianprotocol/ipfs-daemon
IPFS daemon wraps js-ipfs instance with dag-jose codec enabled
npm install dag-jose
Typescript
Module System
Node Version
NPM Version
99.1
Supply Chain
100
Quality
82.9
Maintenance
100
Vulnerability
100
License
TypeScript (76.27%)
JavaScript (23.73%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
NOASSERTION License
50 Stars
48 Commits
11 Forks
4 Watchers
8 Branches
8 Contributors
Updated on Feb 01, 2025
Minified
Minified + Gzipped
Latest Version
5.1.1
Package Id
dag-jose@5.1.1
Unpacked Size
27.42 kB
Size
7.58 kB
File Count
14
NPM Version
10.1.0
Node Version
20.9.0
Published on
Jul 22, 2024
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
2
This library provides a TypeScript implementation of the DAG-JOSE codec for IPLD.
It supports the new multiformats library in order to be compatible with both the current and future js-ipfs implementations.
To create and work with DAG-JOSE compatible JOSE objects we recommend using the dag-jose-utils library.
The following example is available in complete form in example-signing-ipld.mjs.
For independent usage as an IPLD codec:
1import * as Block from 'multiformats/block' 2import { sha256 } from 'multiformats/hashes/sha2' 3import * as dagCbor from '@ipld/dag-cbor' // for decoding the signed payload 4import * as dagJose from 'dag-jose'
Import additional libraries for JWS handling:
1// JWT & utilities 2import { 3 ES256KSigner, 4 createJWS, 5 verifyJWS 6} from 'did-jwt' 7import { 8 encodePayload, 9 toJWSPayload, 10 toJWSStrings 11} from 'dag-jose-utils'
Given a keypair:
1const pubkey = '03fdd57adec3d438ea237fe46b33ee1e016eda6b585c3e27ea66686c2ea5358479' 2const privkey = '278a5de700e29faae8e40e366ec5012b5ec63d36ec77e8a2417154cc1d25383f'
Create a signed envelope block:
1const signer = ES256KSigner(privkey)
2// arbitrary data to DAG-CBOR encode, we get a:
3// { cid:CID, linkedBlock: Uint8Array }
4const payloadBlock = await encodePayload(payload)
5// sign the CID as a JWS using our signer
6const jws = await createJWS(toJWSPayload(payloadBlock), signer)
7
8// createJWS gives us a compact string form JWS, DAG-JOSE will accept both the
9// compact and general (object) form but a round-trip decode will always
10// result in the general form. If we want need `jws` to be isometric regardless
11// of whether it has been round-tripped through DAG-JOSE or straight out of
12// `createJWS()` we can call `toGeneral()` to ensure it is always in the
13// general form.
14// jws = dagJose.toGeneral(jws)
15
16// encode as a DagJWS IPLD block
17const jwsBlock = await Block.encode({ value: jws, codec: dagJose, hasher: sha256 })
18
19// we now have two blocks, a signed envelope and a payload
20// DagJWS envelope:
21// - CID: jwsBlock.cid
22// - Bytes: jwsBlock.bytes
23// Payload:
24// - CID: payloadBlock.cid
25// - Bytes: payloadBlock.linkedBlock
Given a DagJWS envelope block CID, load its bytes, verify the signature and load the linked payload block:
1// validate cid matches bytes and decode dag-jose JWS 2const jwsBlock = await Block.create({ bytes, cid, codec: dagJose, hasher: sha256 }) 3const jwsStrings = toJWSStrings(jwsBlock.value) 4// verify the signatures found in the block against our pubkey 5for (const jws of jwsStrings) { 6 const verifiedKey = verifyJWS(jws, [{ publicKeyHex: pubkey }]) // will throw if it doesn't verify 7 console.log(`Verified JWS envelope \u001b[32m${cid}\u001b[39m with public key:\n\t${verifiedKey.publicKeyHex}`) 8} 9 10const payloadCid = jwsBlock.value.link 11// `store.get()` represents a block store, where `get(cid:string):Uint8Array`, 12// in this example case it's simply a `Map` but it could be any method of 13// fetching bytes for a CID 14const payloadBytes = store.get(payloadCid.toString()) 15// validate payloadCid matches bytes and decode dag-cbor payload 16const payloadBlock = await Block.create({ bytes: payloadBytes, cid: payloadCid, codec: dagCbor, hasher: sha256 }) 17 18// The signed and verified payload is available in `payloadBlock.value`
When using DAG-JOSE (for JWE or JWS) with js-IPFS, you will need to convert it from a raw multiformats style codec to a legacy IPLD codec using blockcodec-to-ipld-format.
The following example is available in complete form in example-ipfs.mjs.
A plain IPLD (without IPFS, for cases where you are managing the block store) version is available in example-ipld.mjs.
1// IPLD & IPFS 2import { create as createIpfs } from 'ipfs' 3import { convert as toLegacyIpld } from 'blockcodec-to-ipld-format' 4 5import * as dagJose from 'dag-jose'
1// JWT & utilities 2import { 3 xc20pDirEncrypter, 4 xc20pDirDecrypter, 5 x25519Encrypter, 6 x25519Decrypter, 7 decryptJWE, 8 createJWE 9} from 'did-jwt' 10import { 11 decodeCleartext, 12 prepareCleartext 13} from 'dag-jose-utils'
1// Miscellaneous crypto libraries to support the examples 2import { randomBytes } from '@stablelib/random' 3import { generateKeyPairFromSeed } from '@stablelib/x25519'
Set up js-IPFS:
1const dagJoseIpldFormat = toLegacyIpld(dagJose)
2
3// Async setup tasks
4async function setup () {
5 console.log('Starting IPFS ...')
6 // Instantiate an IPFS node, that knows how to deal with DAG-JOSE blocks
7 ipfs = await createIpfs({ ipld: { formats: [dagJoseIpldFormat] } })
8}
Encrypt and store a payload using a secret key:
1const storeEncrypted = async (payload, key) => { 2 const dirEncrypter = xc20pDirEncrypter(key) 3 // prepares a cleartext object to be encrypted in a JWE 4 const cleartext = await prepareCleartext(payload) 5 // encrypt into JWE container layout using secret key 6 const jwe = await createJWE(cleartext, [dirEncrypter]) 7 // let IPFS store the bytes using the DAG-JOSE codec and return a CID 8 const cid = await ipfs.dag.put(jwe, { format: dagJoseIpldFormat.codec, hashAlg: 'sha2-256' }) 9 console.log(`Encrypted block CID: \u001b[32m${cid}\u001b[39m`) 10 return cid 11}
Load an encrypted block from a CID and decrypt the payload using a secret key:
1const loadEncrypted = async (cid, key) => { 2 const dirDecrypter = xc20pDirDecrypter(key) 3 const retrieved = await ipfs.dag.get(cid) 4 const decryptedData = await decryptJWE(retrieved.value, dirDecrypter) 5 return decodeCleartext(decryptedData) 6}
Create a key, encrypt and store a block, then load and decrypt it:
1const key = randomBytes(32) 2const secretz = { my: 'secret message' } 3console.log('Encrypting and storing secret:\u001b[1m', secretz, '\u001b[22m') 4const cid = await storeEncrypted(secretz, key) 5const decoded = await loadEncrypted(cid, key) 6console.log('Loaded and decrypted block content:\u001b[1m', decoded, '\u001b[22m')
Encrypt and store a payload using a public key:
1const storeEncrypted = async (payload, pubkey) => { 2 const asymEncrypter = x25519Encrypter(pubkey) 3 // prepares a cleartext object to be encrypted in a JWE 4 const cleartext = await prepareCleartext(payload) 5 // encrypt into JWE container layout using public key 6 const jwe = await createJWE(cleartext, [asymEncrypter]) 7 // let IPFS store the bytes using the DAG-JOSE codec and return a CID 8 const cid = await ipfs.dag.put(jwe, { format: dagJoseIpldFormat.codec, hashAlg: 'sha2-256' }) 9 console.log(`Encrypted block CID: \u001b[32m${cid}\u001b[39m`) 10 return cid 11}
Load an encrypted block from a CID and decrypt the payload using a secret key:
1const loadEncrypted = async (cid, privkey) => { 2 const asymDecrypter = x25519Decrypter(privkey) 3 // decode the DAG-JOSE envelope 4 const retrieved = await ipfs.dag.get(cid) 5 const decryptedData = await decryptJWE(retrieved.value, asymDecrypter) 6 return decodeCleartext(decryptedData) 7}
Create a key pair, encrypt and store a block using the public key, then load and decrypt it using the private key:
1const privkey = randomBytes(32) 2// generate a public key from the existing private key 3const pubkey = generateKeyPairFromSeed(privkey).publicKey 4const secretz = { my: 'secret message' } 5console.log('Encrypting and storing secret with public key:\u001b[1m', secretz, '\u001b[22m') 6const cid = await storeEncrypted(secretz, pubkey) 7const decoded = await loadEncrypted(cid, privkey) 8console.log('Loaded and decrypted block content with private key:\u001b[1m', decoded, '\u001b[22m')
The did-jwt
library only supports x25519
key exchange and XChacha20Poly1305
. If you want to use the dag-jose
codec with other less secure algorithms you can encrypt another library and put the resulting JWE into the dag. Below is an example using the jose library.
1const jwk = jose.JWK.generateSync('oct', 256) 2const cleartext = prepareCleartext({ my: 'secret message' }) 3 4// encrypt and put into ipfs 5const jwe = jose.JWE.encrypt.flattened(cleartext, jwk, { alg: 'dir', enc: 'A128CBC-HS256' }) 6const cid = await ipfs.dag.put(jwe, { format: format.codec, hashAlg: 'sha2-256' }) 7 8// retreive and decrypt object 9const retrived = await ipfs.dag.get(cid) 10const decryptedData = jose.JWE.decrypt(retrived, jwk) 11console.log(decodeCleartext(decryptedData)) 12// output: 13// { my: 'secret message' }
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 10/30 approved changesets -- score normalized to 3
Reason
dependency not pinned by hash detected -- score normalized to 2
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
security policy file not detected
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
10 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-05-26
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More