使用MongoDB生成的_ids作为"秘密数据"(例如,OAuth令牌)

Zan*_*aes 5 mongodb

MongoDB _id字段是否足够随机/不可以充当秘密数据?

例如:如果我正在构建服务器端OAuth,我可以将_id用作用户的OAuth令牌吗?我想这样做是因为它为数据库提供了清洁度和可索引性(例如,"tokens._id"=> oauth_token).

检查MongoDB _id对象的结构,它们似乎确实是随机的,但我确实对一个恶意实体蛮力猜测一个人挥之不去.

mne*_*syn 11

简而言之,没有.Mongo ObjectIds很容易猜到.特别是,在高负载下,这些通常是连续的数字,因为时间戳,机器和进程ID不会改变.如果你看一下Objectid的结构,它们就是由

a 4-byte timestamp, 
a 3-byte machine identifier, 
a 2-byte process id, and 
a 3-byte counter, starting with a random value.
Run Code Online (Sandbox Code Playgroud)

因此,它们几乎没有随机性.我经常在数据库中看到连续的id,例如,如果某个控制器操作会快速连续写入域对象和日志条目.

如果可以猜测时间戳并且机器ID是可确定的(除非你有一个庞大的集群,否则它只剩下五个字节).通过查看一些生成的id,我可以将其减少到50个进程,因此有效熵在28位范围内.这仍然很难猜测,但对于访问令牌来说风险太大了.

使用加密强大的伪随机数生成器代替并从中创建令牌.例如,在.NET中,RNGCryptoServiceProvider允许创建任意长度的随机数据.

作为旁注,我建议在OAuthTokens周围添加一个额外的加密包装器,原因有两个:

a)您希望能够快速确定无效令牌.有效的加密shell可能仍包含无效令牌(已撤销或已过期的授权),但您不必每次都使用强力攻击来访问数据库.还有,客户

b)客户可以一遍又一遍地请求令牌.虽然这不是一项要求,但我所知道的几乎所有系统每次都会返回不同的令牌(无论它们是否自我验证).通常,这是因为令牌本身的有效期有限.这与OAuth拨款的有效期不同.

在数据库中,您真正想要存储的是授权,即某些用户向某个客户端提供的权限.如果删除此授权,则所有令牌都将失效.每次插入新令牌都非常不方便,因为用户必须删除所有令牌才能有效删除应用程序授权.