Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
81d90d8
WIP First Iteration of alternate flow
vchinn04 Feb 24, 2026
038460e
Adjusted existing test cases and tested for both valid scenarios for …
vchinn04 Mar 9, 2026
d144a32
Added Signature Flow Verification Tests
vchinn04 Mar 11, 2026
cc7742b
KC verif revert
vchinn04 Mar 11, 2026
5fe629d
Merge branch 'named-data:main' into certificate_verification_alternat…
vchinn04 Mar 11, 2026
8f0703c
Combine new flow tests into one and clean it up
vchinn04 Mar 15, 2026
7f5dd8b
Move common existing cert validation into a helper function
vchinn04 Mar 16, 2026
01337ee
Move duplicate validation code into a helper function
vchinn04 Mar 16, 2026
6c25c9a
Address PR comments
vchinn04 Mar 23, 2026
ea64346
Fix test name typo
vchinn04 Mar 23, 2026
d8ae22b
Merge pull request #177 from vchinn04/certificate_verification_altern…
tianyuan129 Apr 2, 2026
d9b5b49
Clean up retired certificate flow
greetingsuniverse Apr 29, 2026
73fc3de
remove ignoreValidity
greetingsuniverse Apr 29, 2026
d36b132
fix lint
greetingsuniverse Apr 29, 2026
45d2122
add signature time not in cross schema validity period test
greetingsuniverse Apr 29, 2026
eef8cbc
fix lint
greetingsuniverse Apr 29, 2026
a167dc6
validateSigTime returns true when valid
greetingsuniverse Apr 30, 2026
742798a
remove IgnoreValidity and introduce UseSignatureTime in SVS and repo
greetingsuniverse May 7, 2026
cb6b120
add signature time exception for testbed and ucla root certs
greetingsuniverse May 7, 2026
dd86af7
check expiry for excepted certs
greetingsuniverse May 7, 2026
e05979c
Revert "check expiry for excepted certs"
greetingsuniverse May 7, 2026
31b2217
readd IgnoreValidity
greetingsuniverse May 8, 2026
65e6e8c
fix IgnoreValidity in repo config
greetingsuniverse May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions repo/repo_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@ func (r *Repo) fetchSecurityConfig(name enc.Name) (*tlv.SecurityConfigObject, er

// Repo should validate this as normal command
r.client.ConsumeExt(ndn.ConsumeExtArgs{
Name: name,
TryStore: true,
IgnoreValidity: optional.Some(r.config.IgnoreValidity),
Name: name,
TryStore: true,
UseSignatureTime: optional.Some(true),
IgnoreValidity: optional.Some(r.config.IgnoreValidity),
Callback: func(state ndn.ConsumeState) {
wire = append(wire, state.Content()...)
if state.Error() != nil {
Expand Down
10 changes: 6 additions & 4 deletions repo/repo_svs.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ func (r *RepoSvs) Start() (err error) {
}

snapshot = &ndn_sync.SnapshotNodeHistory{
Client: r.client,
Threshold: r.cmd.HistorySnapshot.Threshold,
IsRepo: true,
IgnoreValidity: optional.Some(r.config.IgnoreValidity),
Client: r.client,
Threshold: r.cmd.HistorySnapshot.Threshold,
IsRepo: true,
UseSignatureTime: optional.Some(true),
IgnoreValidity: optional.Some(r.config.IgnoreValidity),
}
}

Expand All @@ -78,6 +79,7 @@ func (r *RepoSvs) Start() (err error) {
SuppressionPeriod: 500 * time.Millisecond,
PeriodicTimeout: 365 * 24 * time.Hour, // basically never
Passive: true,
UseSignatureTime: optional.Some(true),
IgnoreValidity: optional.Some(r.config.IgnoreValidity),
},
Snapshot: snapshot,
Expand Down
17 changes: 12 additions & 5 deletions std/engine/basic/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ func TestRoute(t *testing.T) {
hitCnt := 0
spec := engine.Spec()

// Fixed SigTime for deterministic test vectors: 2024-01-01 00:00:00 UTC
fixedSigTime := optional.Some(time.Duration(1704067200000) * time.Millisecond)

handler := func(args ndn.InterestHandlerArgs) {
hitCnt += 1
require.Equal(t, []byte(
Expand All @@ -278,6 +281,7 @@ func TestRoute(t *testing.T) {
args.Interest.Name(),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
SigTime: fixedSigTime,
},
enc.Wire{[]byte("test")},
sig.NewTestSigner(enc.Name{}, 0))
Expand All @@ -291,8 +295,8 @@ func TestRoute(t *testing.T) {
require.Equal(t, 1, hitCnt)
buf := tu.NoErr(face.Consume())
require.Equal(t, enc.Buffer(
"\x06\x22\x07\x10\x08\x03not\x08\timportant\x14\x03\x18\x01\x00\x15\x04test"+
"\x16\x03\x1b\x01\xc8",
"\x06\x2c\x07\x10\x08\x03not\x08\timportant\x14\x03\x18\x01\x00\x15\x04test"+
"\x16\x0d\x1b\x01\xc8(\x08\x00\x00\x01\x8c\xc2Q\xf4\x00",
), buf)
})
}
Expand All @@ -302,13 +306,16 @@ func TestPitToken(t *testing.T) {
executeTest(t, func(face *face.DummyFace, engine *basic_engine.Engine, timer *basic_engine.DummyTimer) {
hitCnt := 0
spec := engine.Spec()
// Fixed SigTime for deterministic test vectors: 2024-01-01 00:00:00 UTC
fixedSigTime := optional.Some(time.Duration(1704067200000) * time.Millisecond)

handler := func(args ndn.InterestHandlerArgs) {
hitCnt += 1
data, err := spec.MakeData(
args.Interest.Name(),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
SigTime: fixedSigTime,
},
enc.Wire{[]byte("test")},
sig.NewTestSigner(enc.Name{}, 0))
Expand All @@ -324,9 +331,9 @@ func TestPitToken(t *testing.T) {
))
buf := tu.NoErr(face.Consume())
require.Equal(t, enc.Buffer(
"\x64\x2c\x62\x04\x01\x02\x03\x04\x50\x24"+
"\x06\x22\x07\x10\x08\x03not\x08\timportant\x14\x03\x18\x01\x00\x15\x04test"+
"\x16\x03\x1b\x01\xc8",
"\x64\x36\x62\x04\x01\x02\x03\x04\x50\x2e"+
"\x06\x2c\x07\x10\x08\x03not\x08\timportant\x14\x03\x18\x01\x00\x15\x04test"+
"\x16\x0d\x1b\x01\xc8(\x08\x00\x00\x01\x8c\xc2Q\xf4\x00",
), buf)
})
}
6 changes: 5 additions & 1 deletion std/ndn/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ type ConsumeExtArgs struct {
OnProgress func(status ConsumeState)
// NoMetadata disables fetching RDR metadata (advanced usage).
NoMetadata bool
// UseSignatureTime checks validity period using signature time
UseSignatureTime optional.Optional[bool]
// IgnoreValidity ignores validity period in the validation chain
IgnoreValidity optional.Optional[bool]
}
Expand Down Expand Up @@ -167,7 +169,9 @@ type ValidateExtArgs struct {
CertNextHop optional.Optional[uint64]
// UseDataNameFwHint overrides trust config option.
UseDataNameFwHint optional.Optional[bool]
// IgnoreValidity ignores validity period in the validation chain.
// UseSignatureTime checks validity with signature time
UseSignatureTime optional.Optional[bool]
// IgnoreValidity ignores validity period in the validation chain
IgnoreValidity optional.Optional[bool]
}

Expand Down
4 changes: 4 additions & 0 deletions std/ndn/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ type ExpressCallbackArgs struct {
// IsLocal indicates if a local copy of the Data was found.
// e.g. returned by ExpressR when used with TryStore.
IsLocal bool
// UseSignatureTime checks validity with signature time
UseSignatureTime optional.Optional[bool]
// IgnoreValidity ignores validity period in the validation chain
IgnoreValidity optional.Optional[bool]
}

// InterestHandler represents the callback function for an Interest handler.
Expand Down
3 changes: 3 additions & 0 deletions std/ndn/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type DataConfig struct {
SigNotBefore optional.Optional[time.Time]
SigNotAfter optional.Optional[time.Time]

// Signature time, used to determine time the packet was signed
SigTime optional.Optional[time.Duration]

// Cross Schema attachment
CrossSchema enc.Wire
}
Expand Down
14 changes: 12 additions & 2 deletions std/ndn/spec_2022/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ func (d *Data) SigNonce() []byte {
return nil
}

// (AI GENERATED DESCRIPTION): Returns the signature timestamp of the Data packet (currently unimplemented and returns nil).
// (AI GENERATED DESCRIPTION): Returns the signature timestamp of the Data packet if present, else returns nil.
func (d *Data) SigTime() *time.Time {
return nil
if d.SignatureInfo != nil && d.SignatureInfo.SignatureTime.IsSet() {
return utils.IdPtr(time.UnixMilli(d.SignatureInfo.SignatureTime.Unwrap().Milliseconds()))
} else {
return nil
}
}

// (AI GENERATED DESCRIPTION): Sets the Data packet’s SignatureInfo.SignatureTime to the given time (converted to a millisecond duration) or clears the field if the argument is nil.
Expand Down Expand Up @@ -262,6 +266,11 @@ func (Spec) MakeData(name enc.Name, config *ndn.DataConfig, content enc.Wire, si
if config == nil {
return nil, ndn.ErrInvalidValue{Item: "Data.DataConfig", Value: nil}
}

if !config.SigTime.IsSet() {
config.SigTime = optional.Some(time.Duration(time.Now().UnixMilli()) * time.Millisecond)
}

finalBlock := []byte(nil)
if fbid, ok := config.FinalBlockID.Get(); ok {
finalBlock = fbid.Bytes()
Expand Down Expand Up @@ -289,6 +298,7 @@ func (Spec) MakeData(name enc.Name, config *ndn.DataConfig, content enc.Wire, si

data.SignatureInfo = &SignatureInfo{
SignatureType: uint64(signer.Type()),
SignatureTime: config.SigTime,
}

if key := signer.KeyLocator(); key != nil {
Expand Down
44 changes: 27 additions & 17 deletions std/ndn/spec_2022/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,42 @@ func TestMakeDataBasic(t *testing.T) {
tu.SetT(t)

spec := spec_2022.Spec{}
// Fixed SigTime for deterministic test vectors: 2024-01-01 00:00:00 UTC
fixedSigTime := optional.Some(time.Duration(1704067200000) * time.Millisecond)

data, err := spec.MakeData(
tu.NoErr(enc.NameFromStr("/local/ndn/prefix")),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
SigTime: fixedSigTime,
},
nil,
sig.NewSha256Signer(),
)
require.NoError(t, err)
require.Equal(t, []byte(
"\x06\x42\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix"+
"\x06L\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix"+
"\x14\x03\x18\x01\x00"+
"\x16\x03\x1b\x01\x00"+
"\x17 \x7f1\xe4\t\xc5z/\x1d\r\xdaVh8\xfd\xd9\x94"+
"\xd8'S\x13[\xd7\x15\xa5\x9d%^\x80\xf2\xab\xf0\xb5"),
"\x16\x0d\x1b\x01\x00(\x08\x00\x00\x01\x8c\xc2Q\xf4\x00"+
"\x17 *\x17?\xd6i\xdcB\xd0\xf6G\x1d\x0b\xb6\x93\xd4{\xddw\xc6$\x04\x00\x0eN\xb7\x07\x5c\x80K+O\x86"),
data.Wire.Join())

data, err = spec.MakeData(
tu.NoErr(enc.NameFromStr("/local/ndn/prefix")),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
SigTime: fixedSigTime,
},
enc.Wire{[]byte("01020304")},
sig.NewSha256Signer(),
)
require.NoError(t, err)
require.Equal(t, []byte(
"\x06L\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix"+
"\x06V\x07\x14\x08\x05local\x08\x03ndn\x08\x06prefix"+
"\x14\x03\x18\x01\x00"+
"\x15\x0801020304"+
"\x16\x03\x1b\x01\x00"+
"\x17 \x94\xe9\xda\x91\x1a\x11\xfft\x02i:G\x0cO\xdd!"+
"\xe0\xc7\xb6\xfd\x8f\x9cn\xc5\x93{\x93\x04\xe0\xdf\xa6S"),
"\x16\x0d\x1b\x01\x00(\x08\x00\x00\x01\x8c\xc2Q\xf4\x00"+
"\x17 \xaf\x02\x9d\xf3\x9a\x05s\x83\xefv\x05\xef\x81=\xdb.\xc72$v\x13\xb3\xae\x80\x83+\xe8W\xfeP\x1f}"),
data.Wire.Join())

data, err = spec.MakeData(
Expand All @@ -75,39 +77,43 @@ func TestMakeDataBasic(t *testing.T) {
tu.NoErr(enc.NameFromStr("/E")),
&ndn.DataConfig{
ContentType: optional.None[ndn.ContentType](),
SigTime: fixedSigTime,
},
enc.Wire{},
sig.NewSha256Signer(),
)
require.NoError(t, err)
require.Equal(t, tu.NoErr(hex.DecodeString(
"06300703080145"+
"1400150016031b0100"+
"1720f965ee682c6973c3cbaa7b69e4c7063680f83be93a46be2ccc98686134354b66")),
"063a070308014514001500"+
"160d1b010028080000018cc251f400"+
"1720f7b2d57151cb8d6fe2c616adee9195c9d00f3c422754709f750375bae2e91e30")),
data.Wire.Join())
}

// (AI GENERATED DESCRIPTION): Creates a signed Data packet with the specified name, optional meta‑information (content type, freshness period, final block ID), optional content, and the provided signer.
func TestMakeDataMetaInfo(t *testing.T) {
tu.SetT(t)
spec := spec_2022.Spec{}
// Fixed SigTime for deterministic test vectors: 2024-01-01 00:00:00 UTC
fixedSigTime := optional.Some(time.Duration(1704067200000) * time.Millisecond)

data, err := spec.MakeData(
tu.NoErr(enc.NameFromStr("/local/ndn/prefix/37=%00")),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
Freshness: optional.Some(1000 * time.Millisecond),
FinalBlockID: optional.Some(enc.NewSequenceNumComponent(2)),
SigTime: fixedSigTime,
},
nil,
sig.NewSha256Signer(),
)
require.NoError(t, err)
require.Equal(t, []byte(
"\x06\x4e\x07\x17\x08\x05local\x08\x03ndn\x08\x06prefix\x25\x01\x00"+
"\x14\x0c\x18\x01\x00\x19\x02\x03\xe8\x1a\x03\x3a\x01\x02"+
"\x16\x03\x1b\x01\x00"+
"\x17 \x0f^\xa1\x0c\xa7\xf5Fb\xf0\x9cOT\xe0FeC\x8f92\x04\x9d\xabP\x80o'\x94\xaa={hQ"),
"\x06X\x07\x17\x08\x05local\x08\x03ndn\x08\x06prefix\x25\x01\x00"+
"\x14\x0c\x18\x01\x00\x19\x02\x03\xe8\x1a\x03:\x01\x02"+
"\x16\x0d\x1b\x01\x00(\x08\x00\x00\x01\x8c\xc2Q\xf4\x00"+
"\x17 \xa9v\x8a(\xb3^\xf8\x1c\xce*\xa8\xf2\x14\x81\x8cQ\xcc\xb8I\xc6\xd6\xa7\x99z\x88JKu\x81\xc4[N"),
data.Wire.Join())
}

Expand Down Expand Up @@ -148,19 +154,23 @@ func (testSigner) Public() ([]byte, error) {
func TestMakeDataShrink(t *testing.T) {
tu.SetT(t)
spec := spec_2022.Spec{}
// Fixed SigTime for deterministic test vectors: 2024-01-01 00:00:00 UTC
fixedSigTime := optional.Some(time.Duration(1704067200000) * time.Millisecond)

data, err := spec.MakeData(
tu.NoErr(enc.NameFromStr("/test")),
&ndn.DataConfig{
ContentType: optional.Some(ndn.ContentTypeBlob),
SigTime: fixedSigTime,
},
nil,
testSigner{},
)
require.NoError(t, err)
require.Equal(t, []byte{
0x6, 0x22, 0x7, 0x6, 0x8, 0x4, 0x74, 0x65, 0x73, 0x74, 0x14, 0x3, 0x18, 0x1, 0x0,
0x16, 0xc, 0x1b, 0x1, 0xc8, 0x1c, 0x7, 0x7, 0x5, 0x8, 0x3, 0x4b, 0x45, 0x59,
0x6, 0x2c, 0x7, 0x6, 0x8, 0x4, 0x74, 0x65, 0x73, 0x74, 0x14, 0x3, 0x18, 0x1, 0x0,
0x16, 0x16, 0x1b, 0x1, 0xc8, 0x1c, 0x7, 0x7, 0x5, 0x8, 0x3, 0x4b, 0x45, 0x59,
0x28, 0x8, 0x0, 0x0, 0x1, 0x8c, 0xc2, 0x51, 0xf4, 0x0,
0x17, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0},
data.Wire.Join())
}
Expand Down
20 changes: 12 additions & 8 deletions std/object/client_consume.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (c *Client) consumeObject(state *ConsumeState) {
// if metadata fetching is disabled, just attempt to fetch one segment
// with the prefix, then get the versioned name from the segment.
if state.args.NoMetadata {
c.fetchDataByPrefix(name, state.args.TryStore, state.args.IgnoreValidity.GetOr(false),
c.fetchDataByPrefix(name, state.args.TryStore, state.args.UseSignatureTime.GetOr(false), state.args.IgnoreValidity.GetOr(false),
func(data ndn.Data, err error) {
if err != nil {
state.finalizeError(err)
Expand All @@ -81,7 +81,7 @@ func (c *Client) consumeObject(state *ConsumeState) {
}

// fetch RDR metadata for this object
c.fetchMetadata(name, state.args.TryStore, state.args.IgnoreValidity.GetOr(false),
c.fetchMetadata(name, state.args.TryStore, state.args.UseSignatureTime.GetOr(false), state.args.IgnoreValidity.GetOr(false),
func(meta *rdr.MetaData, err error) {
if err != nil {
state.finalizeError(err)
Expand All @@ -107,6 +107,7 @@ func (c *Client) consumeObjectWithMeta(state *ConsumeState, meta *rdr.MetaData)
func (c *Client) fetchMetadata(
name enc.Name,
tryStore bool,
useSignatureTime bool,
ignoreValidity bool,
callback func(meta *rdr.MetaData, err error),
) {
Expand All @@ -131,9 +132,10 @@ func (c *Client) fetchMetadata(
return
}
c.ValidateExt(ndn.ValidateExtArgs{
Data: args.Data,
SigCovered: args.SigCovered,
IgnoreValidity: optional.Some(ignoreValidity),
Data: args.Data,
SigCovered: args.SigCovered,
UseSignatureTime: optional.Some(useSignatureTime),
IgnoreValidity: optional.Some(ignoreValidity),
Callback: func(valid bool, err error) {
// validate with trust config
if !valid {
Expand Down Expand Up @@ -162,6 +164,7 @@ func (c *Client) fetchMetadata(
func (c *Client) fetchDataByPrefix(
name enc.Name,
tryStore bool,
useSignatureTime bool,
ignoreValidity bool,
callback func(data ndn.Data, err error),
) {
Expand All @@ -186,9 +189,10 @@ func (c *Client) fetchDataByPrefix(
return
}
c.ValidateExt(ndn.ValidateExtArgs{
Data: args.Data,
SigCovered: args.SigCovered,
IgnoreValidity: optional.Some(ignoreValidity),
Data: args.Data,
SigCovered: args.SigCovered,
UseSignatureTime: optional.Some(useSignatureTime),
IgnoreValidity: optional.Some(ignoreValidity),
Callback: func(valid bool, err error) {
if !valid {
callback(nil, fmt.Errorf("%w: validate by prefix failed: %w", ndn.ErrSecurity, err))
Expand Down
7 changes: 4 additions & 3 deletions std/object/client_consume_seg.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,10 @@ func (s *rrSegFetcher) handleResult(args ndn.ExpressCallbackArgs, state *Consume
// The notable exception here is when there is a timeout, which has a separate goroutine.
func (s *rrSegFetcher) handleData(args ndn.ExpressCallbackArgs, state *ConsumeState) {
s.client.ValidateExt(ndn.ValidateExtArgs{
Data: args.Data,
SigCovered: args.SigCovered,
IgnoreValidity: state.args.IgnoreValidity,
Data: args.Data,
SigCovered: args.SigCovered,
UseSignatureTime: state.args.UseSignatureTime,
IgnoreValidity: state.args.IgnoreValidity,
Callback: func(valid bool, err error) {
if !valid {
state.finalizeError(fmt.Errorf("%w: validate seg failed: %w", ndn.ErrSecurity, err))
Expand Down
1 change: 1 addition & 0 deletions std/object/client_trust.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (c *Client) ValidateExt(args ndn.ValidateExtArgs) {
Callback: args.Callback,
OverrideName: overrideName,
UseDataNameFwHint: args.UseDataNameFwHint,
UseSignatureTime: args.UseSignatureTime,
IgnoreValidity: args.IgnoreValidity,
Fetch: func(name enc.Name, config *ndn.InterestConfig, callback ndn.ExpressCallbackFunc) {
config.NextHopId = args.CertNextHop
Expand Down
Loading
Loading