Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use CSPRNG to generate objectIds #73

Merged
merged 1 commit into from
Feb 1, 2016
Merged

Use CSPRNG to generate objectIds #73

merged 1 commit into from
Feb 1, 2016

Conversation

dchest
Copy link
Contributor

@dchest dchest commented Jan 30, 2016

No description provided.

@dchest
Copy link
Contributor Author

dchest commented Jan 30, 2016

I'd also increase the length of result to at least 14 characters (ideally, 20), if possible. Currently objectId has less entropy than even a random uint64: 10log2(62) = ~= 59. If increased to 14, this will give 14log2(62) ~= 83 bits, which is much better. For reference, standard UUID has 122 bits of entropy, smallest AES keys — 128.

@gfosco
Copy link
Contributor

gfosco commented Jan 30, 2016

cc @lacker

@TylerBrock
Copy link
Contributor

Could we also consider the use of MongoDB object id's? There are plenty of optimizations in MongoDB for indexing and querying on the BSON type ObjectId that are not available for strings.

@dchest
Copy link
Contributor Author

dchest commented Jan 31, 2016

@TylerBrock quite doable if IDs are not required to be unguessable, and I already wrote the code for this :)

var os = require('os');
var crypto = require('crypto');

var machineId = crypto.createHash('md5').update(os.hostname()).digest().slice(0, 3);
var objectIdCounter = crypto.randomBytes(4).readUInt32BE() & 0xffffff;

// Returns a unique objectId as a hex string.
function newObjectId() {
  var buf = new Buffer(12);
  // Current time, 4 bytes.
  buf.writeUInt32BE(Math.floor(Date.now() / 1000), 0); 
  // Machine ID, 3 bytes.
  machineId.copy(buf, 4);
  // Process ID, 2 bytes.
  buf.writeUInt16BE(process.pid, 7);
  // Global counter, 3 bytes.
  buf.writeUInt8((objectIdCounter >>> 16) & 0xff, 9);
  buf.writeUInt8((objectIdCounter >>> 8) & 0xff, 10);
  buf.writeUInt8((objectIdCounter >>> 0) & 0xff, 11);
  objectIdCounter = (objectIdCounter + 1) & 0xffffff;
  return buf.toString('hex');
}

This newObjectId returns ObjectID as specified in BSON, as a hex string, e.g.: 56ae43cf4fb904a2a1000000.

@gfosco
Copy link
Contributor

gfosco commented Feb 1, 2016

Due to maintaining compatibility with exports from Parse, we have to keep them in string format... but absolutely we're open to a better method of generating that format. Is this PR ready to go?

As for unguessable, I'd say they need to be.

@dchest
Copy link
Contributor Author

dchest commented Feb 1, 2016

@gfosco MongoDB-like ObjectIDs can be 24-character strings (56ae43cf4fb904a2a1000000), so if the only requirement is to have ObjectID in string format, they will do. Such IDs provide some benefits for indexing, e.g. since they include time in the beginning, if you sort by objectId, the objects will be arranged by creation time. However, they are not unguessable: if you know one objectId (or even if you don't, you can just guess it with a bit more work), you can guess the next ones, as only time and increment is changing:

56af41f14fb9045cca63aa77
56af41f24fb9045cca63aa78
56af41f24fb9045cca63aa79

I'd go with the current PR, which is just a random string, but would increase its length to 20 characters (~119 bits), which would make objectId globally unique, that is you can be sure that the same ID was not and will not be generated ever for the foreseeable future, and they are unguessable:

KYYZa8Bi5g4W8J7CE4LQ
z3BrCDX3N8FgaDEk55fN
AZhMDXQsCGAPBft2a2cp

Please let me know if you'd like me to do this change and I'll update this PR.

@gfosco
Copy link
Contributor

gfosco commented Feb 1, 2016

Lets keep it at 10 right now and have parity between hosted Parse and parse-server. We can definitely increase this default in the future.

gfosco added a commit that referenced this pull request Feb 1, 2016
Use CSPRNG to generate objectIds
@gfosco gfosco merged commit 251ec4d into parse-community:master Feb 1, 2016
montymxb pushed a commit to montymxb/parse-server that referenced this pull request Feb 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants