使用MongoDB生成的_id作为“秘密数据". (例如,OAuth令牌) [英] Using MongoDB generated _ids as "secret data" (eg, OAuth Tokens)

查看:93
本文介绍了使用MongoDB生成的_id作为“秘密数据". (例如,OAuth令牌)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MongoDB _id字段是否足够随机/不可猜测以用作机密数据?

Are MongoDB _id fields sufficiently random / unguessable to act as secret data?

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

For example: if I'm building a server-side OAuth, could I use the _id as the OAuth Token for the user? I want to do this because of the cleanliness & indexability it gives the database (eg, "tokens._id" => oauth_token).

在检查MongoDB _id对象的结构时,它们似乎确实是随机的,但我确实对恶意实体蛮力猜测存在一些担忧.

Inspecting the structure of MongoDB _id objects, they do seem to be decently random, but I do have some lingering concern about a malicious entity brute-force guessing one.

推荐答案

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

In short, no. Mongo ObjectIds are easy to guess. In particular, under high load, these are often consecutive numbers, because timestamp, machine and process id don't change. If you look at the structure of Objectid, they are composed of

a 4-byte timestamp, 
a 3-byte machine identifier, 
a 2-byte process id, and 
a 3-byte counter, starting with a random value.

因此,它们的随机性很小.我经常在数据库中看到连续的ID,例如,如果某些控制器操作写入了一个域对象,而日志条目又快速连续地写入.

Hence, they have very little randomness. I often see consecutive ids in the database, for instance if some controller action writes a domain object, and a log entry in quick succession.

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

If the timestamp can be guessed and the machine id is determinable (which it is unless you have a huge cluster), there are only five bytes left. By looking at a number of generated ids, I can probably reduce that to like 50 processes so the effective entropy is somewhere in the 28 bit range. This is still hard to guess, but it's way too risky for an access token.

请改用具有加密功能的伪随机数生成器,然后从中创建令牌.例如,在.NET中,RNGCryptoServiceProvider允许创建任意长度的随机数据.

Use a cryptographically strong pseudo random number generator instead and create a token from that. For example, in .NET, the RNGCryptoServiceProvider allows to create arbitrary length random data.

作为一个旁注,出于两个原因,我建议在OAuthToken周围附加一个加密包装:

As a sidenote, I suggest to have an additional cryptographic wrapper around your OAuthTokens, for two reasons:

a)您希望能够快速确定无效令牌.有效的密码外壳可能仍会包含无效的令牌(已撤销或过期的赠款),但是您不必每次都遭受蛮力攻击就击中数据库.另外,客户端

a) You want to be able to determine invalid tokens quickly. A valid cryptographic shell might still include an invalid token (a revoked or expired grant), but you don't have to hit the database on brute force attacks every time. Also, the client

b)客户可以反复请求令牌.尽管这不是必需的,但我所知道的几乎所有系统每次都返回不同的令牌(无论它们是否进行自我验证).通常,这是因为令牌本身具有有限的有效期.这与OAuth授权所具有的有效期不同.

b) Clients can request tokens over and over. While it's not a requirement, almost all systems I know return different tokens every time (no matter if they are self-validating or not). Usually, that's because the token itself has a limited validity period. That is not the same validity period that the OAuth grant has.

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

In the database, what you really want to store is the grant, i.e. the permission that was given by some user to some client. If this grant is removed, all tokens become invalid. Inserting a new token every time is very unhandy because the user would have to delete all of them to effective remove the application grant.

这篇关于使用MongoDB生成的_id作为“秘密数据". (例如,OAuth令牌)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆