Skip to content

Commit

Permalink
Merge pull request #2 from zjkmxy/master
Browse files Browse the repository at this point in the history
Add more code snippets
  • Loading branch information
pulsejet authored Feb 27, 2024
2 parents af48283 + 4e9a1d6 commit 2c30637
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 14 deletions.
6 changes: 6 additions & 0 deletions docs/communication.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Make sure to start NFD on your development machine before running this example.
--8<-- "snippets/communication/producer.py"
```

=== "NDNts"

``` typescript
--8<-- "snippets/communication/producer.ts"
```

## Faces

!!! warning "Under Construction"
26 changes: 24 additions & 2 deletions docs/security.md → docs/ndn-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,19 @@ Digital signing is done by a pair of asymmetric keys, which consists of a privat
The _private key_ is known only by the producer, used to generate signatures.
Anyone who knows the _public key_ can verify the signature.

(Code snippet to be added)

=== "python-ndn"

``` python
--8<-- "snippets/security/key-gen.py"
```

=== "NDNts"

``` typescript
--8<-- "snippets/security/key-gen.ts"
```


In a system, security is more than cryptographically verifying the signature.
For example, we also need to
Expand Down Expand Up @@ -56,7 +68,17 @@ The entity (member or process) that owns the trust anchor has the power to contr
Entities managing the trust relationship of the trust domain (including memberships and roles) are called _controllers_.
The owner of the trust anchor is always a controller.

(Code snippet to be added)
=== "python-ndn"

``` python
--8<-- "snippets/security/trust-domain.py"
```

=== "NDNts"

``` typescript
--8<-- "snippets/security/trust-domain.ts"
```

An application may involve multiple trust domains. _Inter-domain trust relations_ will be established by the controller.
In the case where pure peer-to-peer trust relation is established, every member is its own controller.
Expand Down
14 changes: 13 additions & 1 deletion docs/testbed.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,16 @@

The NDN research testbed is a shared resource created for research purposes, that include software routers at several participating institutions, application host nodes, and other devices. The testbed is used for research and development of NDN software, and for experiments that require a shared NDN infrastructure. It is not intended for production use.

[https://named-data.net/ndn-testbed/](https://named-data.net/ndn-testbed/)
[https://named-data.net/ndn-testbed/](https://named-data.net/ndn-testbed/)

## Obtain a testbed certificate

See [User Guide to Obtain a Testbed Certificate](https://named-data.net/ndn-testbed/user-guide-to-obtain-a-testbed-certificate/)

## Connect to testbed using local NFD

TBD

## Connect to testbed from application

TBD
22 changes: 11 additions & 11 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ plugins:
csl_file: acm-sig-proceedings.csl

nav:
- "index.md"
- "getting-started.md"
- "packets.md"
- "communication.md"
- "security.md"
- "sync.md"
- "storage.md"
- "forwarding.md"
- "routing.md"
- "testbed.md"
- "debugging.md"
- 'index.md'
- 'getting-started.md'
- 'packets.md'
- 'communication.md'
- 'ndn-security.md'
- 'sync.md'
- 'storage.md'
- 'forwarding.md'
- 'routing.md'
- 'testbed.md'
- 'debugging.md'

markdown_extensions:
- admonition
Expand Down
24 changes: 24 additions & 0 deletions snippets/communication/producer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Data, digestSigning } from '@ndn/packet';
import { WsTransport } from '@ndn/ws-transport';
import { Endpoint } from '@ndn/endpoint';
import { toUtf8 } from '@ndn/util';

// Code running in the browser cannot connect to a local Unix socket.
// In this example, we connect to a remote NFD instance, running as
// a part of the global NDN testbed.
const uplink = await WsTransport.createFace({}, "wss://suns.cs.ucla.edu/ws/");
console.log(`Connected to NFD at ${uplink.remoteAddress}`);

// Construct an Endpoint on the default forwarder instance.
const endpoint = new Endpoint();

// Start one producer
const myProducer = endpoint.produce('/edu/ucla/cs/118/notes', async (interest) => {
console.log(`Received Interest packet for ${interest.name.toString()}`);
// Create the content bytes for the Data packet
const content = toUtf8("Hello, NDN!");
// Sign and send the Data packet back to the network
const data = new Data(interest.name, Data.FreshnessPeriod(10000), content);
await digestSigning.sign(data);
return data;
});
32 changes: 32 additions & 0 deletions snippets/security/key-gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ndn.encoding as enc
import ndn.security as sec
from Cryptodome.PublicKey import ECC

# Generate key pairs (Recommend 'P-256' for ECDSA and 'ed25519' for EdDSA)
priv_key = ECC.generate(curve='ed25519')
pub_key = priv_key.public_key()
# Create a signer
signer = sec.Ed25519Signer('/edu/ucla/xinyu.ma', priv_key.export_key(format='DER'))
# Sign a data with it
data_wire = enc.make_data(
# String can be directly used as Name in most cases
name='/edu/ucla/cs/118/notes',
# Set the Interest packet's FreshnessPeriod to 10 seconds
meta_info=enc.MetaInfo(freshness_period=10000),
# Set the Data packet's content to "Hello, NDN!"
content=b'Hello, NDN!',
signer=signer
)
print('Data:', data_wire.hex())

# Export public keys
pub_key_bits = pub_key.export_key(format='DER')
print('Public Key bits:', pub_key_bits.hex())
# Can be imported by: ECC.import_key(pub_key_bits)

# Then verify the Data packet using it
_, _, _, sig_ptrs = enc.parse_data(data_wire)
if sec.verify_ed25519(pub_key, sig_ptrs):
print('Data verified')
else:
print('Data not verified')
33 changes: 33 additions & 0 deletions snippets/security/key-gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Data, Name } from '@ndn/packet';
import { Decoder, Encoder } from '@ndn/tlv';
import { toHex, toUtf8 } from '@ndn/util';
import { Ed25519, generateSigningKey } from '@ndn/keychain';

// Generate key pairs (Recommend ECDSA and Ed25519 for EdDSA)
const identityName = new Name('/edu/ucla/xinyu.ma');
const [signer, verifier] = await generateSigningKey(identityName, Ed25519);
// Sign a Data with it
const data = new Data(
new Name('/edu/ucla/cs/118/notes'),
Data.FreshnessPeriod(10000),
toUtf8('Hello, NDN!'));
await signer.sign(data);
// Print the Data wire
const wire = Encoder.encode(data);
console.log('Data:', toHex(wire));

// Export public keys
const publicKeyBits = verifier.spki!;
console.log('Public Key bits:', toHex(publicKeyBits));
// Importing a public key in NDNts is very complicated
// so I recommend to use a certificate instead.
// I will show you how to do it later.

// Then verify the Data packet using it
const decodedData = Decoder.decode(wire, Data); // Be the same as `data`
try {
await verifier.verify(decodedData);
console.log('Data verified');
} catch {
console.log('Data not verified');
}
58 changes: 58 additions & 0 deletions snippets/security/trust-domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from datetime import datetime, timedelta, timezone
import ndn.encoding as enc
import ndn.security as sec
import ndn.app_support.security_v2 as secv2
from Cryptodome.PublicKey import ECC
from Cryptodome.Random import get_random_bytes


# Generate trust anchor of admin
admin_priv = ECC.generate(curve='ed25519')
admin_pub = admin_priv.public_key()
admin_pub_bits = admin_pub.export_key(format='DER')
admin_identity_name = enc.Name.from_str('/lab/admin')
# Key name is <IdentityName>/KEY/<keyId>, here we use random value as key ID.
# You can also use timestamp, sequencial number, or hash.
admin_key_name = enc.Name.normalize(
admin_identity_name + ['KEY', enc.Component.from_bytes(get_random_bytes(8))])
# Self signer is used to sign the self-signed certificate only.
admin_self_signer = sec.Ed25519Signer(
admin_key_name, admin_priv.export_key(format='DER'))
anchor_name, anchor = secv2.self_sign(
admin_key_name, admin_pub_bits, admin_self_signer)
# We create a new signer with this certificate's name for further use
admin_signer = sec.Ed25519Signer(
anchor_name, admin_priv.export_key(format='DER'))
print(f'Admin trust anchor name: {enc.Name.to_str(anchor_name)}')
print(f'Admin trust anchor hex: {bytes(anchor).hex()}')
print()

# Generate the student's key and issue him a certificate
stu_priv = ECC.generate(curve='ed25519')
stu_pub = stu_priv.public_key()
stu_pub_bits = stu_pub.export_key(format='DER')
stu_identity_name = enc.Name.from_str('/lab/student/xinyu.ma')
stu_key_name = enc.Name.normalize(
stu_identity_name + ['KEY', enc.Component.from_bytes(get_random_bytes(8))])
stu_cert_name, stu_cert = secv2.new_cert(
stu_key_name,
'admin',
stu_pub_bits,
admin_signer,
start_time=datetime.now(timezone.utc),
end_time=datetime.now(timezone.utc) + timedelta(days=365),
)
stu_signer = sec.Ed25519Signer(
stu_cert_name, stu_priv.export_key(format='DER'))
print(f'Student certificate name: {enc.Name.to_str(stu_cert_name)}')
print(f'Student certificate hex: {bytes(stu_cert).hex()}')
print()

# Sign the paper's data with the student's certificate
data_wire = enc.make_data(
name='/lab/paper/ndn/change/1',
meta_info=enc.MetaInfo(freshness_period=10000),
content=b'Hello, NDN!',
signer=stu_signer
)
print('Data:', data_wire.hex())
47 changes: 47 additions & 0 deletions snippets/security/trust-domain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Component, Data, Name } from '@ndn/packet';
import { Encoder } from '@ndn/tlv';
import { toHex, toUtf8 } from '@ndn/util';
import { Certificate, Ed25519, generateSigningKey, ValidityPeriod } from '@ndn/keychain';

// Generate trust anchor of admin
const adminIdentityName = new Name('/lab/admin');
const [adminSelfSigner, adminVerifier] = await generateSigningKey(adminIdentityName, Ed25519);
const anchor = await Certificate.selfSign({
privateKey: adminSelfSigner,
publicKey: adminVerifier,
});
const adminSigner = adminSelfSigner.withKeyLocator(anchor.name);
const anchorWire = Encoder.encode(anchor.data);
console.log(`Admin trust anchor name: ${anchor.name.toString()}`);
console.log(`Admin trust anchor hex: ${toHex(anchorWire)}`);
console.log('');
// The following line create the verifier from certificate
// const anchor = Certificate.fromData(Decoder.decode(anchorWire, Data));
// const adminVerifier = await createVerifier(anchor, {algoList: [Ed25519]});

// Generate the student's key and issue him a certificate
const stuIdentityName = new Name('/lab/student/xinyu.ma');
const [stuSelfSigner, stuVerifier] = await generateSigningKey(stuIdentityName, Ed25519);
const stuCert = await Certificate.issue({
issuerPrivateKey: adminSigner,
publicKey: stuVerifier,
issuerId: new Component(8, 'admin'),
// Equivalent to the following:
// validity: new ValidityPeriod(Date.now(), Date.now() + 365 * 86400000),
validity: ValidityPeriod.daysFromNow(365),
});
const stuSigner = stuSelfSigner.withKeyLocator(stuCert.name);
const stuCertWire = Encoder.encode(stuCert.data);
console.log(`Student certificate name: ${stuCert.name.toString()}`);
console.log(`Student certificate hex: ${toHex(stuCertWire)}`);
console.log('');

// Sign the paper's data with the student's certificate
const data = new Data(
new Name('/lab/paper/ndn/change/1'),
Data.FreshnessPeriod(10000),
toUtf8('Hello, NDN!'),
);
await stuSigner.sign(data);
const dataWire = Encoder.encode(data);
console.log('Data:', toHex(dataWire));

0 comments on commit 2c30637

Please sign in to comment.