Comments (11)
So, Coze defines iat and rvk as integers, and assumes implementations are able to represent those values as integers to at least 2^53-1. That's fine! Just throw it in the docs and all good.
from coze.
This specification allows implementations to set limits on the range and precision of numbers accepted. Since software that implements IEEE 754 binary64 (double precision) numbers (IEEE754) is generally available and widely used, good interoperability can be achieved by implementations that expect no more precision or range than these provide . . .
Note that when such software is used, numbers that are integers and are in the range [-(253)+1, (253)-1] are interoperable in the sense that implementations will agree exactly on their numeric values.
If you want to make this assumption, that's fine! Just worth some documentation :)
from coze.
When I receive the JSON string {"iat":1680217459}
it is not guaranteed that my in-memory value of iat
will be precisely the uint32/uint64 integer 1680217459. If I model iat as a int16 it may be 65535, if I model it as a float64 it may be 1680217459.0001. So when I generate the sign bytes there is no guarantee that I will re-create {"iat":1680217459}
precisely, I could generate {"iat":65535}
or {"iat":1680217459.000}
or {"iat":1680217459.0000009}
or whatever else and it would be totally JSON valid. JSON numbers are always approximations. If you want reliably reproducible values you can't use numbers. Strictly speaking.
from coze.
The spec currently reads for rvk
:
Coze requires rvk to be an integer with a maximum value of 9,007,199,254,740,991 (2^53 – 1), which is Javascript's MAX_SAFE_INTEGER. Checking for revoked when rvk's value is a non-integer or value past MAX_SAFE_INTEGER must error.
The Go implementation currently does not apply this rule (and probably should).
The numbers section from the RFC says:
Note that when such software is used, numbers that are integers and
are in the range [-(2**53)+1, (2**53)-1] are interoperable in the
sense that implementations will agree exactly on their numeric
values.
I believe that works and I don't think time values needs to be a string. As long as the integer is smaller than 2^53 – 1 it would generally consider it to be interoperable. Most modern systems use 64 bits for Unix timestamps and those that don't are migrating to 64 bits.
I think a good change would be for Coze to define iat
with the same constraints as rvk
.
from coze.
It seems that this is from the discussion on Lobste.rs
As far as rvk
and iat
, I think the above covers that well.
Yes, it would be ideal for Coze to be bijective, but we may consider it outside
of our purview. Systems that do weird things with JSON may not expect to be
interoperable or bijective with other systems and constraining JSON in such a way could fall
outside the scope of Coze. We can however rigidly apply requirements to fields
that Coze defines.
Alternatively, we can just apply the I-JSON standard, which
includes good constraints on numbers. Bray has a lot of great advice for best practices for JSON.
from coze.
@peterbourgon, I've followed your works for a while and I'm thrilled that Coze has interested you. Thank you!
I'm re-reading the I-JSON spec at the moment. It might be a good idea for Coze to apply it entirely.
from coze.
I mean, the easiest solution here is to represent your times not as integer UNIX seconds-since-epoch, but as string RFC3339 timestamps as UTC. What's the downside?
from coze.
I might be missing something. What's wrong with a Unix timestamp, UTC?
Cozies are UTF-8 encoded. {"iat":1680217459}
always encodes as the same byte string which is what is signed.
from coze.
Coze implicitly assumes that systems can at least represent 32 bit numbers by
defining iat
and rvk
as integer Unix time stamps. The
Go
and Javascript implementations both use sufficiently large integers internally
when storing the timestamp. Presently, any system that's capable of representing
32 bit numbers is compatible with cozies that use current time Unix timestamps.
In the future systems suffering from the Year 2038 problem may experience issues,
but that's not a problem specific to Coze.
This is only an issue for implementers that do not internally use a lossless
datatype for 32 bit integers. We could require Coze to specify system must
support integers up to 9,007,199,254,740,991 (2^53 – 1) for rvk
and iat
. I
believe that would resolve the bijective encoding concerns for all reasonable
timestamps. Implementations that don't have a 53 bit integer type available can
simply internally store those integers as strings, but that doesn't have to be
something specified by Coze as that is a problem for the implementations to
resolve.
So to summarize, we can add this line to the spec:
`iat` and `rvk` must be an integer of value up to 9,007,199,254,740,991 (2^53 – 1).
rvk
I believe already meets these requirements, at least implicitly. The
constraint just needs to be expanded to include iat
.
from coze.
Concerning only iat
, there is another concern that we came across today.
Function Verify
may verify a digest that over a pay
with an
invalid iat
and there is no way to know. This means VerifyCoze
and Verify
will have inconsistent behavior for the same payload. For this reason, I think
it's a bad idea to require iat
to adhere to the MAX_SAFE_INTEGER rule and
instead the specification can specify iat
"should adhere" to the rule.
It's easy to implement the "iat
must be less than 2^53 - 1" rule. The check can exist in func (p *Pay) UnmarshalJSON(b []byte) error
, which is then called by VerifyCoze()
const MAX_SAFE_INTEGER = 9007199254740992
...
if iat > MAX_SAFE_INTEGER{
return fmt.Errorf("UnmarshalJSON: iat value over 2^53 - 1 (9,007,199,254,740,991)")
}
The difference boils down to Coze interpreting iat
, which seems overbearing,
while requiring interpreting rvk
seems reasonable. For revoke messages, rvk
is always known and checkable, so a "must adhere" continues to seem reasonable.
Critically, a "must" for rvk
ensures systems agree what keys are revoked. For
iat
, if system verify digest only messages (they might not even have access to
the original payload), there is no way to tell. Downstream system need to be
aware of this difference between iat
and rvk
and appropriately handle this
edge case if they desire a "must adhere" for iat
. I don't think hiding this complexity in Coze libraries is the
correct answer for iat
.
In view of the above, the Coze specification should be updated with the following:
`rvk` must and `iat` should be an integer less than 9,007,199,254,740,991 (2^53
– 1), which is the integer precision limit specified by IEEE754 minus one.
Revoke checks must error if `rvk`'s is not an integer or larger than 2^53 - 1.
More generally, Coze must make no rule requiring any sort of interpretation of
the contents of pay
. alg
and tmb
are the only exceptions since this
information must be at least implicitly known by Verify. No other information is needed to verify a given digest.
from coze.
This is addressed by commit e279528 and I consider this concern resolved.
from coze.
Related Issues (20)
- MapItem is unsafe, and MapSlice does not have a well-defined order HOT 53
- JSON round-trip fails for MapSlice HOT 4
- Expunge "cryptographic agility" from Coze vocabulary HOT 2
- Make new repositories for the specification and implementations
- Use JSONv2 when production ready HOT 2
- Further constraints on Ed25519
- Base64 encoding can only elide padding when the size of encoded data is known HOT 7
- Enforce Canonical Base 64 encoding. HOT 3
- Think about adding "MustMarshal" and "MarshalPretty"
- Consider documenting that `rvk` denotes expiry for Coze keys. HOT 2
- implement pure python or python wrapper lib HOT 2
- implement kyber (liboqs) ciphers for Coze HOT 3
- Unsigned Alg and Tmb
- Active HOT 5
- Duplicate JSON keys create misleading verification results in the web UI HOT 1
- Issues HOT 2
- 404 in Readme.md HOT 1
- Locally hosted Cyphr.me's verifier.
- Godoc in 1.19 does not appear to link to packages as documented.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from coze.