Security News
Weekly Downloads Now Available in npm Package Search Results
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
@ndn/packet
Advanced tools
This package is part of NDNts, Named Data Networking libraries for the modern web.
This package implements Name, Interest, and Data types as specified in NDN Packet Format v0.3.
import { TT, Name, Component, ImplicitDigest,
Interest, Data, LLSign, LLVerify, canSatisfy, canSatisfySync } from "@ndn/packet";
// other imports for examples
import { Decoder, Encoder } from "@ndn/tlv";
import { strict as assert } from "assert";
import { timingSafeEqual } from "crypto";
(async () => {
// Name components are immutable. Once it's created, you can never change it.
// Construct a Component from its TLV-TYPE and TLV-VALUE.
const compA = new Component(TT.GenericNameComponent, Uint8Array.of(0x41));
// Create a Component from URI representation.
const compB = Component.from("B");
// Typed components are supported, too.
const compMetadata = Component.from("32=metadata");
// We can retrieve TLV-TYPE, TLV-LENGTH, and TLV-VALUE.
assert.equal(compA.type, TT.GenericNameComponent);
assert.equal(compB.type, TT.GenericNameComponent);
assert.equal(compMetadata.type, 0x20);
assert.equal(compA.length, 1);
assert.equal(compB.length, 1);
assert.equal(compMetadata.length, 8);
assert.deepEqual(compA.value, Uint8Array.of(0x41));
assert.deepEqual(compB.value, Uint8Array.of(0x42));
assert.deepEqual(compMetadata.value, Uint8Array.of(0x6D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61));
// For convenience, we can retrieve TLV-VALUE as text string, too.
assert.equal(compA.text, "A");
assert.equal(compB.text, "B");
assert.equal(compMetadata.text, "metadata");
// Components are comparable.
assert.equal(compA.compare(compA), Component.CompareResult.EQUAL);
assert.equal(compA.compare(compB), Component.CompareResult.LT);
assert.equal(compB.compare(compA), Component.CompareResult.GT);
assert.equal(compA.equals(compA), true);
assert.equal(compA.equals(compB), false);
// Names, like components, are immutable.
// Construct from URI.
const name1 = new Name("/localhost/NDNts/rocks");
// Construct from a list of components, or strings to create components.
const name2 = new Name([compA, compB, "C", compMetadata]);
// You can always convert a name back to its URI.
assert.equal(name1.toString(), "/localhost/NDNts/rocks");
assert.equal(name2.toString(), "/A/B/C/32=metadata");
// It's crucial to know how many name components you have.
assert.equal(name1.length, 3);
assert.equal(name2.length, 4);
// You can get an individual name component.
const name1comp1 = name1.get(1);
// It would return 'undefined' if the component does not exist, so we have to check.
if (typeof name1comp1 === "undefined") {
assert.fail(); // This isn't supposed to happen for this name, though.
} else {
assert.equal(name1comp1.text, "NDNts");
}
// To save the 'undefined' check, use at(i). It throws if the component does not exist.
assert.throws(() => name1.at(5));
assert.equal(name1.at(1).text, "NDNts");
// Slice the name to obtain part of it.
const name1sliced = name1.slice(1, 3);
assert.equal(name1sliced.toString(), "/NDNts/rocks");
// Or, get the prefix.
const name2prefix = name2.getPrefix(3);
assert.equal(name2prefix.toString(), "/A/B/C");
// Indexing from the back is supported, too.
assert.equal(name1.at(-1).text, "rocks");
assert.equal(name1.slice(-2).toString(), "/NDNts/rocks");
assert.equal(name2.getPrefix(-1).toString(), "/A/B/C");
// Names are comparable.
const nameAB = new Name("/A/B");
const nameABB = new Name("/A/B/B");
const nameABC = new Name("/A/B/C");
const nameABD = new Name("/A/B/D");
const nameABCD = new Name("/A/B/C/D");
assert.equal(nameABC.equals(nameABC), true);
assert.equal(nameABC.equals(nameABD), false);
assert.equal(nameABC.compare(nameABC), Name.CompareResult.EQUAL);
assert.equal(nameABC.compare(nameABB), Name.CompareResult.GT);
assert.equal(nameABC.compare(nameABD), Name.CompareResult.LT);
assert.equal(nameABC.compare(nameABCD), Name.CompareResult.LPREFIX);
assert.equal(nameABC.compare(nameAB), Name.CompareResult.RPREFIX);
// LPREFIX means the first name is a strict prefix of the second name.
// It implies the first name is less than the second name.
// If you only care about the order, check if the result is less than zero.
assert(nameABC.compare(nameABCD) < 0);
// RPREFIX means the second name is a strict prefix of the first name.
// It implies the first name is greater than the second name.
// If you only care about the order, check if the result is greater than zero.
assert(nameABC.compare(nameAB) > 0);
// If you want to know whether a name is a prefix of another, it's EQUAL or LPREFIX.
// But we got a faster way:
assert.equal(nameABC.isPrefixOf(nameABC), true);
assert.equal(nameABC.isPrefixOf(nameABCD), true);
assert.equal(nameABC.isPrefixOf(nameAB), false);
// I said names are immutable, but you can surely modify them to get a new Name.
const name1modified = name1.getPrefix(-1).append("is", "awesome");
assert(name1modified.toString(), "/localhost/NDNts/rocks/is/awesome");
assert(name1.toString(), "/localhost/NDNts/rocks"); // unchanged
// We have an Interest type, of course.
// You can set fields via constructor or setters.
const interest = new Interest(new Name("/A"), Interest.CanBePrefix, Interest.MustBeFresh);
interest.canBePrefix = false;
interest.lifetime = 2000;
// Encode and decode the Interest.
const interestWire = Encoder.encode(interest);
const interest2 = new Decoder(interestWire).decode(Interest);
assert.equal(interest2.name.toString(), "/A");
// We got a Data type, too.
// You can set fields via constructor or setters.
const data = new Data(interest.name, Data.FreshnessPeriod(5000));
data.content = new TextEncoder().encode("hello NDNts");
// Every NDN Data must be signed.
// This package only provides a low-level API, which is crude to use directly.
// Nevertheless, this is how it works.
// Our signature would be 'DDDD'.
const expectedSignature = Uint8Array.of(0xDD, 0xDD);
// First, set a signing function on [LLSign.PENDING] property.
data[LLSign.PENDING] = async (input: Uint8Array): Promise<Uint8Array> => {
return Promise.resolve(expectedSignature);
};
// Then, process the signing operations asynchronously.
await data[LLSign.PROCESS]();
// Finally, we can encode the Data and then decode it.
const dataWire = Encoder.encode(data);
const data2 = new Decoder(dataWire).decode(Data);
// Data signature should be verified.
// Again, this is a low-level API, so it would look difficult.
// Signed portion is already saved during decoding.
assert(data2[LLVerify.SIGNED] instanceof Uint8Array);
// Invoke [LLVerify.VERIFY] with a crypto verification function.
await data2[LLVerify.VERIFY]((input: Uint8Array, sig: Uint8Array) => {
return new Promise<void>((resolve, reject) => {
timingSafeEqual(sig, expectedSignature) ? resolve() : reject();
});
});
// It's very important that you do not modify the Data if you need to verify its signature.
// Otherwise, you'll get errors or incorrect results.
// Now we can access the Content.
assert.equal(new TextDecoder().decode(data2.content), "hello NDNts");
// To obtain implicit digest, we'll have to await, because it internally uses WebCrypto, which is async.
const digest = await data.computeImplicitDigest();
assert.equal(digest.length, 32);
// Full names are available, too.
const fullName = await data2.computeFullName();
assert.equal(fullName.length, data2.name.length + 1);
assert(fullName.at(-1).is(ImplicitDigest));
// After computation, implicit digest is cached on the Data instance,
// so we can get them without await:
const digest2 = data.getImplicitDigest();
const fullName2 = data.getFullName();
assert.equal(digest2, digest);
assert(typeof fullName2 !== "undefined");
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
assert.equal(fullName2!.toString(), fullName.toString());
// Note that these functions are only available after encoding or decoding.
// Calling them on a Data before encoding results in an error.
assert.throws(() => new Data().getImplicitDigest());
assert.throws(() => new Data().getFullName());
assert.rejects(new Data().computeImplicitDigest());
assert.rejects(new Data().computeFullName());
// Also, if you modify the Data after encoding or decoding, you'll get incorrect results.
// In short, only call them right after encoding or decoding.
// To determine whether a Data satisfy an Interest, use canSatisfy or canSatisfySync.
// canSatisfySync returns a boolean:
assert.equal(canSatisfySync(interest, data), true);
const interest3 = new Interest("/B");
assert.equal(canSatisfySync(interest3, data), false);
// However, it does not support implicit digest, because digest computation is async:
const data3 = new Decoder(dataWire).decode(Data);
const interestWithFullName = new Interest(fullName);
assert(typeof canSatisfySync(interestWithFullName, data3) === "undefined");
// Unless the Data contains cached implicit digest:
assert.equal(canSatisfySync(interestWithFullName, data), true);
// canSatisfy returns a Promise that resolves to boolean, which can support implicit digest.
assert.equal(await canSatisfy(interestWithFullName, data3), true);
})();
FAQs
NDNts: Network Layer Packets
The npm package @ndn/packet receives a total of 1 weekly downloads. As such, @ndn/packet popularity was classified as not popular.
We found that @ndn/packet demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
Security News
A Stanford study reveals 9.5% of engineers contribute almost nothing, costing tech $90B annually, with remote work fueling the rise of "ghost engineers."
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.