Skip to content

Commit 5c589da

Browse files
authored
fix: remove value ambiguity (#109)
We accept strings as values to publish, but the actual datatype is Uint8Array. Likewise these Uint8Arrays get turned into strings when passed back, but in JavaScript this can be a lossy translation as bytes values above 127 are interpreted as multi-byte UTF8 code points. This PR removes strings as acceptible input types and only accepts Uint8Arrays. BREAKING CHANGE: strings are no longer accepted as valid values to publish
1 parent 20031ce commit 5c589da

File tree

2 files changed

+25
-26
lines changed

2 files changed

+25
-26
lines changed

src/index.js

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,46 +38,46 @@ const namespace = '/ipns/'
3838
* Note: This function does not embed the public key. If you want to do that, use `EmbedPublicKey`.
3939
*
4040
* @param {PrivateKey} privateKey - private key for signing the record.
41-
* @param {string} value - value to be stored in the record.
41+
* @param {Uint8Array} value - value to be stored in the record.
4242
* @param {number} seq - number representing the current version of the record.
43-
* @param {number|string} lifetime - lifetime of the record (in milliseconds).
43+
* @param {number} lifetime - lifetime of the record (in milliseconds).
4444
*/
4545
const create = (privateKey, value, seq, lifetime) => {
4646
// Validity in ISOString with nanoseconds precision and validity type EOL
4747
const isoValidity = new NanoDate(Date.now() + Number(lifetime)).toString()
4848
const validityType = ipnsEntryProto.ValidityType.EOL
49-
return _create(privateKey, value, seq, isoValidity, validityType)
49+
return _create(privateKey, value, seq, uint8ArrayFromString(isoValidity), validityType)
5050
}
5151

5252
/**
5353
* Same as create(), but instead of generating a new Date, it receives the intended expiration time
5454
* WARNING: nano precision is not standard, make sure the value in seconds is 9 orders of magnitude lesser than the one provided.
5555
*
5656
* @param {PrivateKey} privateKey - private key for signing the record.
57-
* @param {string} value - value to be stored in the record.
57+
* @param {Uint8Array} value - value to be stored in the record.
5858
* @param {number} seq - number representing the current version of the record.
5959
* @param {string} expiration - expiration datetime for record in the [RFC3339]{@link https://www.ietf.org/rfc/rfc3339.txt} with nanoseconds precision.
6060
*/
6161
const createWithExpiration = (privateKey, value, seq, expiration) => {
6262
const validityType = ipnsEntryProto.ValidityType.EOL
63-
return _create(privateKey, value, seq, expiration, validityType)
63+
return _create(privateKey, value, seq, uint8ArrayFromString(expiration), validityType)
6464
}
6565

6666
/**
6767
* @param {PrivateKey} privateKey
68-
* @param {string} value
68+
* @param {Uint8Array} value
6969
* @param {number} seq
70-
* @param {string} isoValidity
70+
* @param {Uint8Array} isoValidity
7171
* @param {number} validityType
7272
*/
7373
const _create = async (privateKey, value, seq, isoValidity, validityType) => {
7474
const signature = await sign(privateKey, value, validityType, isoValidity)
7575

7676
const entry = {
77-
value: uint8ArrayFromString(value),
77+
value,
7878
signature: signature,
7979
validityType: validityType,
80-
validity: uint8ArrayFromString(isoValidity),
80+
validity: isoValidity,
8181
sequence: seq
8282
}
8383

@@ -248,9 +248,9 @@ const getIdKeys = (pid) => {
248248
* Sign ipns record data
249249
*
250250
* @param {PrivateKey} privateKey
251-
* @param {string} value
251+
* @param {Uint8Array} value
252252
* @param {number} validityType
253-
* @param {Uint8Array | string} validity
253+
* @param {Uint8Array} validity
254254
*/
255255
const sign = (privateKey, value, validityType, validity) => {
256256
try {
@@ -281,19 +281,11 @@ const getValidityType = (validityType) => {
281281
/**
282282
* Utility for creating the record data for being signed
283283
*
284-
* @param {string | Uint8Array} value
284+
* @param {Uint8Array} value
285285
* @param {number} validityType
286-
* @param {string | Uint8Array} validity
286+
* @param {Uint8Array} validity
287287
*/
288288
const ipnsEntryDataForSig = (value, validityType, validity) => {
289-
if (!(value instanceof Uint8Array)) {
290-
value = uint8ArrayFromString(value)
291-
}
292-
293-
if (!(validity instanceof Uint8Array)) {
294-
validity = uint8ArrayFromString(validity)
295-
}
296-
297289
const validityTypeBuffer = uint8ArrayFromString(getValidityType(validityType))
298290

299291
return uint8ArrayConcat([value, validity, validityTypeBuffer])
@@ -327,14 +319,21 @@ const marshal = (obj) => {
327319
*/
328320
const unmarshal = (buf) => {
329321
const message = ipnsEntryProto.decode(buf)
330-
331-
// @ts-ignore
332-
return ipnsEntryProto.toObject(message, {
322+
const object = ipnsEntryProto.toObject(message, {
333323
defaults: false,
334324
arrays: true,
335325
longs: Number,
336326
objects: false
337327
})
328+
329+
return {
330+
value: object.value,
331+
signature: object.signature,
332+
validityType: object.validityType,
333+
validity: object.validity,
334+
sequence: object.sequence,
335+
pubKey: object.pubKey
336+
}
338337
}
339338

340339
const validator = {

test/index.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const ERRORS = require('../src/errors')
2222
describe('ipns', function () {
2323
this.timeout(20 * 1000)
2424

25-
const cid = 'QmWEekX7EZLUd9VXRNMRXW3LXe4F6x7mB8oPxY5XLptrBq'
25+
const cid = uint8ArrayFromString('QmWEekX7EZLUd9VXRNMRXW3LXe4F6x7mB8oPxY5XLptrBq')
2626

2727
/** @type {{ id: string, publicKey: string }} */
2828
let ipfsId
@@ -44,7 +44,7 @@ describe('ipns', function () {
4444

4545
const entry = await ipns.create(rsa, cid, sequence, validity)
4646
expect(entry).to.deep.include({
47-
value: uint8ArrayFromString(cid),
47+
value: cid,
4848
sequence: sequence
4949
})
5050
expect(entry).to.have.property('validity')

0 commit comments

Comments
 (0)