当读取rand.Reader时可能会导致错误吗?

huangapple go评论158阅读模式
英文:

When reading rand.Reader may result in error?

问题

我是否正确理解,crypto/rand.Reader 只会在未列出的平台上返回读取错误,即当它实际上未被实现时?

// Reader 是一个全局共享的强加密伪随机生成器实例。
//
// 在 Linux 上,如果可用,Reader 使用 getrandom(2),否则使用 /dev/urandom。
// 在 OpenBSD 上,Reader 使用 getentropy(2)。
// 在其他类 Unix 系统上,Reader 从 /dev/urandom 读取。
// 在 Windows 系统上,Reader 使用 CryptGenRandom API。
var Reader io.Reader

英文:

Do I understand correctly that crypto/rand.Reader can return Read error only on platforms not listed below, i.e. when it is not actually implemented?

// Reader is a global, shared instance of a cryptographically
// strong pseudo-random generator.
//
// On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise.
// On OpenBSD, Reader uses getentropy(2).
// On other Unix-like systems, Reader reads from /dev/urandom.
// On Windows systems, Reader uses the CryptGenRandom API.
var Reader io.Reader

答案1

得分: 10

TL;DRcrypto/randRead()(和Reader.Read())方法可能因各种原因而失败,即使在支持的平台上也是如此。不要假设调用这些函数会始终成功。始终检查error返回值。

>我理解正确,crypto/rand.Reader只会在未列出的平台上返回读取错误,即实际上未实现时才会返回错误吗?

不是。例如,看一下rand.ReaderLinux实现。如果可用,该实现将使用getrandom Linux系统调用,该调用可能会失败并返回多个错误(最重要的是EAGAIN):

> EAGAIN - 请求的熵不可用,并且如果未设置GRND_NONBLOCK标志,getrandom()将阻塞。

EAGAIN错误字面上告诉你“稍后再试”;根据man 3 errno的官方含义是“资源暂时不可用”。因此,当收到EAGAIN错误时,你可以简单地在一定时间内继续尝试。

如果getrandom不可用,crypto/rand模块将尝试打开并从/dev/urandom读取(参见源代码),这也可能因各种原因而失败。这些错误可能不一定是暂时性的(例如,与文件系统权限有关的问题);如果你的应用程序依赖于随机数据的可用性,你应该将错误视为应用程序中的任何其他不可恢复的错误。

因此,你不应该假设rand.Read()在Linux/UNIX上总是成功,并且始终检查rand.Read()的错误返回值。

英文:

TL;DR; crypto/rand's Read() (and Reader.Read()) methods may fail due to a variety of reasons, even on the platforms listed as supported. Do not assume that calls to this functions will always succeed. Always check the error return value.

<hr />

>Do I understand correctly that crypto/rand.Reader can return Read error only on platforms not listed below, i.e. when it is not actually implemented?

No. For example, have a look at the Linux implementation of rand.Reader. If available, this implementation will use the getrandom Linux system call, which may fail with a number of errors (most importantly, EAGAIN):

> EAGAIN - The requested entropy was not available, and getrandom() would
have blocked if the GRND_NONBLOCK flag was not set.

The EAGAIN error quite literally tells you to "try again later"; the official meaning according to man 3 errno is "Resource temporarily unavailable". So when receiving an EAGAIN error you could simply keep trying for a certain time.

If getrandom is not available, the crypto/rand module will try to open and read from /dev/urandom (see source code), which might also fail for any number of reasons. These errors might not necessarily be of temporary nature (for example, issues with file system permissions); if your application depends on the availability of random data, you should treat an error like any other kind of non-recoverable error in your application.

For these reasons, you should not assume that rand.Read() will always succeed on Linux/UNIX and always check rand.Read()'s error return value.

答案2

得分: 0

type io.Reader

Reader是封装基本Read方法的接口。

Read将最多len(p)个字节读入p中。它返回读取的字节数(0 <= n <= len(p))和遇到的任何错误。即使Read返回n < len(p),在调用期间它也可能使用p的所有内容作为临时空间。如果有一些数据可用但不足len(p)个字节,Read通常会返回可用的数据,而不是等待更多数据。

当Read在成功读取n > 0个字节后遇到错误或文件结束条件时,它返回读取的字节数。它可以从同一次调用中返回(非nil)错误,也可以从后续调用中返回错误(以及n == 0)。这种一般情况的一个实例是,在输入流的末尾返回非零字节数的Reader可能返回err == EOF或err == nil。下一次Read应该返回0,EOF。

在考虑错误err之前,调用者应始终处理返回的n > 0个字节。这样做可以正确处理在读取一些字节后发生的I/O错误,以及两种允许的EOF行为。

除非len(p) == 0,否则不建议Read的实现返回零字节计数和nil错误。调用者应将返回的0和nil视为表示什么都没有发生;特别是它不表示EOF。

实现不得保留p。

type Reader interface {
        Read(p []byte) (n int, err error)
}

不,io.Reader会返回错误。

英文:

> type io.Reader
>
> Reader is the interface that wraps the basic Read method.
>
> Read reads up to len(p) bytes into p. It returns the number of bytes
> read (0 <= n <= len(p)) and any error encountered. Even if Read
> returns n < len(p), it may use all of p as scratch space during the
> call. If some data is available but not len(p) bytes, Read
> conventionally returns what is available instead of waiting for more.
>
> When Read encounters an error or end-of-file condition after
> successfully reading n > 0 bytes, it returns the number of bytes read.
> It may return the (non-nil) error from the same call or return the
> error (and n == 0) from a subsequent call. An instance of this general
> case is that a Reader returning a non-zero number of bytes at the end
> of the input stream may return either err == EOF or err == nil. The
> next Read should return 0, EOF.
>
> Callers should always process the n > 0 bytes returned before
> considering the error err. Doing so correctly handles I/O errors that
> happen after reading some bytes and also both of the allowed EOF
> behaviors.
>
> Implementations of Read are discouraged from returning a zero byte
> count with a nil error, except when len(p) == 0. Callers should treat
> a return of 0 and nil as indicating that nothing happened; in
> particular it does not indicate EOF.
>
> Implementations must not retain p.
>
> type Reader interface {
> Read(p []byte) (n int, err error)
> }

No. io.Readers return errors.

huangapple
  • 本文由 发表于 2017年2月19日 00:58:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/42317996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定