2017-02-18 23 views
1

私はそれが実際に実装されていない時に暗号化/ rand.Readerはすなわち、唯一以下に記載されていないプラットフォーム上の読み取りエラーを返すことができるということ?正しく理解していますかrand.Readerを読むとエラーが発生する可能性がありますか?

// 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 

答えて

5

TL; DRcrypto/randRead()(およびReader.Read())の方法は、サポートされているプラ​​ットフォームであっても、さまざまな理由で失敗する可能性があります。 は、この関数の呼び出しが常に成功するとは限りません。 常にerrorの戻り値を確認してください。


私はそれが実際に実装されていない時に暗号化/ rand.Readerはすなわち、唯一の下に記載されていないプラットフォーム上での読み取りエラーを返すことができることを正しく理解していますか?

いいえ。たとえば、Linux implementationrand.Readerです。可能な場合、この実装は、(最も重要なのは、EAGAIN)エラーの数で失敗可能性がある、getrandom Linux system callを使用します。

EAGAIN - 要求されたエントロピーが利用できなかった、とgetrandom()GRND_NONBLOCKフラグ場合 ブロックされているだろう設定されていませんでした。

EAGAINエラーは文字どおり「後でやり直してください」と伝えます。 man 3 errnoの正式な意味は"リソースは一時的に利用できません"です。だからEAGAINエラーを受け取ったら、単に一定の時間だけ試してみることができます。

getrandomが使用できない場合は、crypto/randモジュールはまた、任意の数の理由で失敗する可能性がある、(source codeを参照)開き、/dev/urandomから読み取るしようとします。これらのエラーは、必ずしも一時的なものではない場合があります(たとえば、ファイルシステムのアクセス許可に関する問題)。アプリケーションがランダムなデータの可用性に依存している場合は、アプリケーションで他の種類の回復不能なエラーのようにエラーを処理する必要があります。これらの理由から

、あなたはないrand.Read()はいつものLinux/UNIXと常にチェックrand.Read()のエラーの戻り値に成功することを前提とすべきです。

+0

ありがとう@helmbert。 'rand.Reader.Read'が失敗し、ランダムに生成された番号が進まなければならないときに、プログラムが何をすべきか知っていますか?別の実装を使用するか、再試行するか(?)など何かを実行する必要がありますか? – kopiczko

+0

'EAGAIN'エラーは文字通り"後でやり直してください "と言っています。 ['man 3 errno'](http://man7.org/linux/man-pages/man3/errno.3.html)による正式な意味は、*リソースは一時的に利用できません。だから、 'EAGAIN'エラーを受け取ったら、単に一定の時間だけ試してみることができます。一方、 '/ dev/urandom'からのエントロピーの読み込みは、一時的ではないかもしれないいくつかの理由(ファイルシステムのパーミッションなど)で失敗する可能性があります。これは、他の種類の回復不可能なエラー例えば、妥当なエラーメッセージを出力してプログラムを終了させるなど)。 – helmbert

1

type io.Reader

Readerは、基本的なReadメソッドをラップインタフェースです。

読み取りは、pにlen(p)バイトまで読み取ります。これは、バイト数 (0 < = n < = len(p))と発生したエラーを返します。 Read がn < len(p)を返したとしても、 呼び出し中にすべてのpをスクラッチスペースとして使用することがあります。いくつかのデータが利用可能であるがlen(p)バイトではない場合、Read は通常、より多くを待つ代わりに利用可能なものを返します。

がn> 0バイトを正常に読み取った後、読み取りでエラーまたはファイルの終わりの条件が発生すると、読み取られたバイト数が返されます。 同じ呼び出しから(非nil)エラーを返したり、後続の呼び出しで エラー(およびn == 0)を返します。この一般的な例の場合、 の場合、入力ストリームの最後の に0以外のバイト数を返すReaderは、err == EOFまたはerr == nilのいずれかを返す可能性があります。 次のReadは0、EOFを返します。

呼び出し元は、エラーエラーを考慮して、 より前に返されたn> 0バイトを常に処理する必要があります。そうすることで、いくつかのバイトを読み取った後に が発生するI/Oエラーと、許可されたEOF ビヘイビアの両方が正しく処理されます。読むの

実装は、LEN(P)== 0発信者が 何も起こらなかったことを示すように0とゼロのリターンを扱う必要がある場合を除いてはnilエラーでゼロバイト 数を返すから落胆しています。 で特にEOFを示していません。

実装では、pを保持してはいけません。

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

io.Reader Sリターンエラー。

+1

すべてのリーダーがエラーを返すわけではありません。例えば。 'math/rand.Rand'。そして、ある実装がエラーを返すことになっていることが時々分かっています。 – kopiczko

関連する問題