cipher

package
v1.21.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 9, 2023 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package cipherは、低レベルのブロック暗号実装を包み込むことができる標準のブロック暗号モードを実装しています。 詳細はhttps://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html およびNIST Special Publication 800-38Aを参照してください。

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AEAD added in v1.2.0

type AEAD interface {
	// NonceSize returns the size of the nonce that must be passed to Seal
	// and Open.
	NonceSize() int

	// Overhead returns the maximum difference between the lengths of a
	// plaintext and its ciphertext.
	Overhead() int

	// Seal encrypts and authenticates plaintext, authenticates the
	// additional data and appends the result to dst, returning the updated
	// slice. The nonce must be NonceSize() bytes long and unique for all
	// time, for a given key.
	//
	// To reuse plaintext's storage for the encrypted output, use plaintext[:0]
	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
	Seal(dst, nonce, plaintext, additionalData []byte) []byte

	// Open decrypts and authenticates ciphertext, authenticates the
	// additional data and, if successful, appends the resulting plaintext
	// to dst, returning the updated slice. The nonce must be NonceSize()
	// bytes long and both it and the additional data must match the
	// value passed to Seal.
	//
	// To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
	//
	// Even if the function fails, the contents of dst, up to its capacity,
	// may be overwritten.
	Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
}

AEADは関連データを含めた認証暗号化を提供する暗号モードです。手法の説明については、以下を参照してください。 https://en.wikipedia.org/wiki/Authenticated_encryption.

func NewGCM added in v1.2.0

func NewGCM(cipher Block) (AEAD, error)

NewGCMは、標準のnonce長でラップされた128ビットのブロック暗号を返します。

一般的に、GCMのこの実装で実行されるGHASH操作は一定時間ではありません。 aes.NewCipherで生成された基礎のブロックが、AESのハードウェアサポートを持つシステムである場合は例外です。詳細については、crypto/aesパッケージのドキュメントを参照してください。

Example (Decrypt)
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
)

func main() {

	// 安全な場所から秘密のキーを読み込み、複数のSeal/Open呼び出し間で再利用してください。
	// (もちろん、実際の用途にはこの例のキーを使用しないでください。)
	// パスフレーズをキーに変換したい場合は、bcryptやscryptなどの適切なパッケージを使用してください。
	// キーをデコードすると、16バイト(AES-128)または32バイト(AES-256)である必要があります。
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	ciphertext, _ := hex.DecodeString("c3aaa29f002ca75870806e44086700f62ce4d43e902b3888e23ceff797a7a471")
	nonce, _ := hex.DecodeString("64a9433eae7ccceee2fc0eda")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err.Error())
	}

	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		panic(err.Error())
	}

	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}

	fmt.Printf("%s\n", plaintext)
}
Output:

exampleplaintext
Example (Encrypt)
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/crypto/rand"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密鍵を読み込み、複数のSeal/Open呼び出しで再利用します。
	//(もちろん、実際の用途にはこの例の鍵を使用しないでください。)
	// パスフレーズを鍵に変換したい場合は、bcryptやscryptのような適切な
	// パッケージを使用してください。
	// デコードされた鍵は16バイト(AES-128)または32バイト(AES-256)である必要があります。
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	plaintext := []byte("exampleplaintext")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err.Error())
	}

	// 同じキーで2^32以上のランダムなノンスを使用しないでください。繰り返しのリスクがあるためです。
	nonce := make([]byte, 12)
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		panic(err.Error())
	}

	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		panic(err.Error())
	}

	ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
	fmt.Printf("%x\n", ciphertext)
}
Output:

func NewGCMWithNonceSize added in v1.5.0

func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error)

NewGCMWithNonceSize は、与えられた長さの非スタンダードなノンスを受け付ける、128-bitのブロック暗号をGalios Counter Modeでラップしたものを返します。長さはゼロであってはいけません。 他の暗号システムとの互換性が必要な場合にのみ、この関数を使用してください。他のユーザーは、より高速でミス使用に対してより抵抗力のあるNewGCMを使用すべきです。

func NewGCMWithTagSize added in v1.11.0

func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error)

NewGCMWithTagSizeは、指定された128ビットのブロック暗号をGalois Counter Modeでラップし、指定された長さのタグを生成します。 12バイトから16バイトのタグサイズが許可されています。 非標準のタグ長を使用する既存の暗号システムとの互換性が必要な場合にのみ、この関数を使用してください。その他のユーザーは、誤用に対してより耐性があるNewGCMを使用するべきです。

type Block

type Block interface {
	// BlockSize returns the cipher's block size.
	BlockSize() int

	// Encrypt encrypts the first block in src into dst.
	// Dst and src must overlap entirely or not at all.
	Encrypt(dst, src []byte)

	// Decrypt decrypts the first block in src into dst.
	// Dst and src must overlap entirely or not at all.
	Decrypt(dst, src []byte)
}

A Block represents an implementation of block cipher using a given key. It provides the capability to encrypt or decrypt individual blocks. The mode implementations extend that capability to streams of blocks. ブロックは与えられた鍵を使用したブロック暗号の実装を表します。個々のブロックを暗号化または復号する機能を提供します。モードの実装は、ブロックのストリームにこの機能を拡張します。

type BlockMode

type BlockMode interface {
	// BlockSize returns the mode's block size.
	BlockSize() int

	// CryptBlocks encrypts or decrypts a number of blocks. The length of
	// src must be a multiple of the block size. Dst and src must overlap
	// entirely or not at all.
	//
	// If len(dst) < len(src), CryptBlocks should panic. It is acceptable
	// to pass a dst bigger than src, and in that case, CryptBlocks will
	// only update dst[:len(src)] and will not touch the rest of dst.
	//
	// Multiple calls to CryptBlocks behave as if the concatenation of
	// the src buffers was passed in a single run. That is, BlockMode
	// maintains state and does not reset at each CryptBlocks call.
	CryptBlocks(dst, src []byte)
}

BlockModeは、ブロックベースのモード(CBC、ECBなど)で動作するブロック暗号を表します。

func NewCBCDecrypter

func NewCBCDecrypter(b Block, iv []byte) BlockMode

NewCBCDecrypterは、与えられたBlockを使用して、暗号ブロックチェーンモードで復号化するためのBlockModeを返します。ivの長さは、Blockのブロックサイズと同じでなければならず、データの暗号化に使用されたivと一致する必要があります。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
)

func main() {

	// 安全な場所から秘密鍵を読み込んで、複数の NewCipher 呼び出し間で再利用してください。
	// (もちろん、実際の用途にはこの例の鍵を使用しないでください。)
	// パスフレーズを鍵に変換したい場合は、bcrypt や scrypt のような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	ciphertext, _ := hex.DecodeString("73c86d43a9d700a253a96c85b0f6b03ac9792e0e757f869cca306bd3cba1c62b")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVは一意である必要がありますが、セキュリティは必要ありません。
	// そのため、しばしば暗号文の先頭に含まれます。
	if len(ciphertext) < aes.BlockSize {
		panic("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	// CBCモードは常に完全なブロックで動作します。
	if len(ciphertext)%aes.BlockSize != 0 {
		panic("ciphertext is not a multiple of the block size")
	}

	mode := cipher.NewCBCDecrypter(block, iv)

	// CryptBlocks は、引数が同じであればその場で処理されます。
	mode.CryptBlocks(ciphertext, ciphertext)

	// もし元の平文の長さがブロックの倍数でない場合、暗号化する際に追加する必要があるパディングがこの時点で削除されます。例としては、https://tools.ietf.org/html/rfc5246#section-6.2.3.2 を参照してください。ただし、パディングオラクルを作成しないために、暗号文を複合化する前に必ず認証すること(つまり、crypto/hmacを使用すること)が非常に重要です。

	fmt.Printf("%s\n", ciphertext)
}
Output:

exampleplaintext

func NewCBCEncrypter

func NewCBCEncrypter(b Block, iv []byte) BlockMode

NewCBCEncrypterは、与えられたBlockを使用して、暗号ブロック連鎖モードで暗号化するBlockModeを返します。ivの長さは、Blockのブロックサイズと同じでなければなりません。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/crypto/rand"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密の鍵をロードし、複数の NewCipher 呼び出しで再利用します。
	// (もちろん、実際の目的にはこの例の鍵を使用しないでください。)
	// もしパスフレーズを鍵に変換したい場合は、bcrypt や scrypt のような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	plaintext := []byte("exampleplaintext")

	// CBCモードでは、平文はブロック単位で処理されるため、次の完全なブロックまでパディングする必要がある場合があります。このようなパディングの例については、次を参照してください:https://tools.ietf.org/html/rfc5246#section-6.2.3.2。ここでは、平文が既に正しい長さであると仮定します。
	if len(plaintext)%aes.BlockSize != 0 {
		panic("plaintext is not a multiple of the block size")
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVはユニークである必要がありますが、セキュリティは求められません。
	// そのため、一般的には暗号文の先頭に含めることがあります。
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)

	// 暗号文は、安全にするために暗号化されるだけでなく、
	// (つまり、crypto/hmacを使用することによって)認証されている必要があることを忘れないことが重要です。

	fmt.Printf("%x\n", ciphertext)
}
Output:

type Stream

type Stream interface {
	// XORKeyStream XORs each byte in the given slice with a byte from the
	// cipher's key stream. Dst and src must overlap entirely or not at all.
	//
	// If len(dst) < len(src), XORKeyStream should panic. It is acceptable
	// to pass a dst bigger than src, and in that case, XORKeyStream will
	// only update dst[:len(src)] and will not touch the rest of dst.
	//
	// Multiple calls to XORKeyStream behave as if the concatenation of
	// the src buffers was passed in a single run. That is, Stream
	// maintains state and does not reset at each XORKeyStream call.
	XORKeyStream(dst, src []byte)
}

Streamはストリーム暗号を表します。

func NewCFBDecrypter

func NewCFBDecrypter(block Block, iv []byte) Stream

NewCFBDecrypterは、暗号フィードバックモードで復号化するStreamを返します。 ブロックとして指定されたものを使用します。IVはブロックのサイズと同じ長さでなければならない。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
)

func main() {

	// 安全な場所から秘密キーを読み込み、複数のNewCipher呼び出しで再利用してください。
	// (もちろん、実際にはこの例のキーを使用しないでください。)パスフレーズをキーに変換したい場合は、bcryptやscryptなど適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	ciphertext, _ := hex.DecodeString("7dd015f06bec7f1b8f6559dad89f4131da62261786845100056b353194ad")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVは一意である必要がありますが、安全性は問われません。したがって、通常は暗号文の先頭に含まれます。
	if len(ciphertext) < aes.BlockSize {
		panic("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	// もし2つの引数が同じ場合、XORKeyStreamはインプレースで動作することができます。
	stream.XORKeyStream(ciphertext, ciphertext)
	fmt.Printf("%s", ciphertext)
}
Output:

some plaintext

func NewCFBEncrypter

func NewCFBEncrypter(block Block, iv []byte) Stream

NewCFBEncrypterは、与えられたブロックを使用して、暗号フィードバックモードで暗号化するストリームを返します。IVはブロックのブロックサイズと同じ長さでなければなりません。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/crypto/rand"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密鍵を読み込み、複数の NewCipher 呼び出しで再利用してください。 (明らかに、実際の何かのためにこの例の鍵を使用しないでください)。 パスフレーズを鍵に変換したい場合は、bcrypt や scrypt のような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	plaintext := []byte("some plaintext")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVは一意である必要がありますが、安全である必要はありません。したがって、一般的には、暗号文の先頭にIVを含めることがあります。
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	// 暗号文は、安全性を確保するために、暗号化だけでなく、認証(crypto/hmac の使用によって)も行われる必要があることを覚えておくことが重要です。
	fmt.Printf("%x\n", ciphertext)
}
Output:

func NewCTR

func NewCTR(block Block, iv []byte) Stream

NewCTRは、指定されたブロックを使用して暗号化/復号化を行うStreamを返します。 ivの長さは、ブロックのブロックサイズと同じでなければなりません。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/crypto/rand"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密キーを読み込み、複数のNewCipher呼び出しで再利用します。
	// (もちろん、実際の用途にはこの例のキーを使用しないでください。)
	// パスフレーズをキーに変換したい場合は、bcryptやscryptのような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	plaintext := []byte("some plaintext")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVは一意である必要がありますが、セキュリティは必要ありません。そのため、一般的には暗号文の先頭に含まれます。
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCTR(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	// 暗号文は安全にするために、暗号化するだけでなく、認証(つまりcrypto/hmacを使用すること)することも重要であることを忘れないようにする必要があります。

	// CTR モードは暗号化と復号化の両方に同じですので、NewCTR を使ってその暗号文を復号化することもできます。

	plaintext2 := make([]byte, len(plaintext))
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])

	fmt.Printf("%s\n", plaintext2)
}
Output:

some plaintext

func NewOFB

func NewOFB(b Block, iv []byte) Stream

NewOFBは、ブロック暗号bを使用して暗号化または復号化するStreamを返します。 初期化ベクトルivの長さは、bのブロックサイズと等しくなければなりません。

Example
package main

import (
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/crypto/rand"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密鍵を読み込み、複数の NewCipher 呼び出しで再利用します。
	//(もちろん、実際の用途にはこの例の鍵を使用しないでください。)もしパスフレーズを鍵に変換したい場合は、bcrypt や scrypt のような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")
	plaintext := []byte("some plaintext")

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// IVは一意である必要がありますが、セキュリティは必要ありません。そのため、一般的には
	// 暗号文の先頭に含まれています。
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewOFB(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	// 暗号文だけでなく、(crypto/hmacを使用して)認証も行われる必要があることを覚えておくことは重要です。これによってセキュリティが確保されます。

	// OFBモードは暗号化と復号化の両方において同じですので、NewOFBを使ってその暗号文を復号化することも可能です。

	plaintext2 := make([]byte, len(plaintext))
	stream = cipher.NewOFB(block, iv)
	stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])

	fmt.Printf("%s\n", plaintext2)
}
Output:

some plaintext

type StreamReader

type StreamReader struct {
	S Stream
	R io.Reader
}

StreamReaderはStreamをio.Readerにラップします。それは各データスライスを通過する際にXORKeyStreamを呼び出して処理します。

Example
package main

import (
	"github.com/shogo82148/std/bytes"
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/io"
	"github.com/shogo82148/std/os"
)

func main() {

	// 安全な場所から秘密の鍵をロードし、複数の NewCipher 呼び出しで再利用してください。
	// (もちろん、これは実際には使用しないでください。)パスフレーズを鍵に変換したい場合は、bcrypt や scrypt のような適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")

	encrypted, _ := hex.DecodeString("cf0495cc6f75dafc23948538e79904a9")
	bReader := bytes.NewReader(encrypted)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// もしキーがそれぞれの暗号文ごとにユニークである場合、ゼロの初期化ベクトル(IV)を使用しても問題ありません。
	var iv [aes.BlockSize]byte
	stream := cipher.NewOFB(block, iv[:])

	reader := &cipher.StreamReader{S: stream, R: bReader}
	// 入力を出力ストリームにコピーし、逐次復号化する。
	if _, err := io.Copy(os.Stdout, reader); err != nil {
		panic(err)
	}

	// この例では、暗号化されたデータの認証を省略しているため、単純化されています。実際にこのようにStreamReaderを使用する場合、攻撃者は出力の任意のビットを反転させることができます。

}
Output:

some secret text

func (StreamReader) Read

func (r StreamReader) Read(dst []byte) (n int, err error)

type StreamWriter

type StreamWriter struct {
	S   Stream
	W   io.Writer
	Err error
}

StreamWriterはStreamをio.Writerにラップします。それはXORKeyStreamを呼び出して 通過するデータの各スライスを処理します。もしWrite呼び出しがshortを返す場合、 StreamWriterは同期が取れておらず、破棄する必要があります。 StreamWriterには内部のバッファリングはなく、データを書き込むためにCloseを呼び出す必要はありません。

Example
package main

import (
	"github.com/shogo82148/std/bytes"
	"github.com/shogo82148/std/crypto/aes"
	"github.com/shogo82148/std/crypto/cipher"
	"github.com/shogo82148/std/encoding/hex"
	"github.com/shogo82148/std/fmt"
	"github.com/shogo82148/std/io"
)

func main() {

	// 安全な場所から秘密キーを読み込み、複数の NewCipher 呼び出しで再利用します。
	// (もちろん、実際の用途でこの例のキーを使用しないでください。)
	// もしパスフレーズをキーに変換したい場合は、bcrypt や scrypt のような
	// 適切なパッケージを使用してください。
	key, _ := hex.DecodeString("6368616e676520746869732070617373")

	bReader := bytes.NewReader([]byte("some secret text"))

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// キーが各暗号文ごとにユニークな場合、ゼロのIVを使用することは問題ありません。
	var iv [aes.BlockSize]byte
	stream := cipher.NewOFB(block, iv[:])

	var out bytes.Buffer

	writer := &cipher.StreamWriter{S: stream, W: &out}
	// 入力を出力バッファにコピーし、進行中に暗号化します。
	if _, err := io.Copy(writer, bReader); err != nil {
		panic(err)
	}

	// この例は暗号化されたデータの認証を省略して簡略化しています。実際にStreamReaderをこのように使用する場合、攻撃者が復号化された結果内の任意のビットを反転させる可能性があります。

	fmt.Printf("%x\n", out.Bytes())
}
Output:

cf0495cc6f75dafc23948538e79904a9

func (StreamWriter) Close

func (w StreamWriter) Close() error

Closeは基礎となるWriterを閉じ、そのCloseの返り値を返します。Writerがio.Closerでもある場合は、それを返します。そうでなければnilを返します。

func (StreamWriter) Write

func (w StreamWriter) Write(src []byte) (n int, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL