Documentation
¶
Overview ¶
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() int
Overhead() int
Seal(dst, nonce, plaintext, additionalData []byte) []byte
Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
}
AEAD is a cipher mode providing authenticated encryption with associated data. For a description of the methodology, see https://en.wikipedia.org/wiki/Authenticated_encryption.
func NewGCM ¶ added in v1.2.0
NewGCMは、与えられた128ビットのブロック暗号を標準のナンス長でGalois Counter Modeでラップしたものを返します。
一般的に、GCMのこの実装で実行されるGHASH操作は一定時間ではありません。 aes.NewCipherで生成された基礎の Block が、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())
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
// Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
nonce := make([]byte, aesgcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); 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
NewGCMWithNonceSize は、与えられた長さの非スタンダードなノンスを受け付ける、128-bitのブロック暗号をGalios Counter Modeでラップしたものを返します。長さはゼロであってはいけません。 他の暗号システムとの互換性が必要な場合にのみ、この関数を使用してください。他のユーザーは、より高速でミス使用に対してより抵抗力のある NewGCM を使用すべきです。
func NewGCMWithRandomNonce ¶ added in v1.25.0
NewGCMWithRandomNonceは、与えられた暗号をランダムに生成されたナンスを使用してGalois Counter Modeでラップしたものを返します。暗号は crypto/aes.NewCipher によって作成されている必要があります。
この関数は96ビットのランダムナンスを生成し、Sealによって暗号文の先頭に付加され、 Openによって暗号文から抽出されます。AEADのNonceSizeは0であり、 Overheadは28バイト(ナンスサイズとタグサイズの組み合わせ)です。
ランダムナンスの衝突リスクを無視できるレベルに制限するため、 与えられた鍵は2^32個を超えるメッセージの暗号化に使用してはいけません。
func NewGCMWithTagSize ¶ added in v1.11.0
NewGCMWithTagSizeは、指定された128ビットのブロック暗号をGalois Counter Modeでラップし、指定された長さのタグを生成します。 12バイトから16バイトのタグサイズが許可されています。 非標準のタグ長を使用する既存の暗号システムとの互換性が必要な場合にのみ、この関数を使用してください。その他のユーザーは、誤用に対してより耐性がある NewGCM を使用するべきです。
type Block ¶
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 ¶
BlockModeは、ブロックベースのモード(CBC、ECBなど)で動作するブロック暗号を表します。
func NewCBCDecrypter ¶
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 ¶
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(dst, src []byte)
}
Streamはストリーム暗号を表します。
func NewCFBDecrypter
deprecated
NewCFBDecrypterは、与えられた Block を使用して、暗号フィードバックモードで復号化する Stream を返します。 ivは Block のブロックサイズと同じ長さである必要があります。
Deprecated: CFBモードは認証されておらず、一般的に平文を操作して復元するアクティブ攻撃を可能にします。 アプリケーションでは代わりに AEAD モードを使用することを推奨します。CFBの標準ライブラリ実装は 最適化されておらず、FIPS 140-3モジュールの一部として検証されていません。 認証されていない Stream モードが必要な場合は、代わりに NewCTR を使用してください。
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
deprecated
NewCFBEncrypterは、与えられた Block を使用して、暗号フィードバックモードで暗号化する Stream を返します。 ivは Block のブロックサイズと同じ長さである必要があります。
Deprecated: CFBモードは認証されておらず、一般的に平文を操作して復元するアクティブ攻撃を可能にします。 アプリケーションでは代わりに AEAD モードを使用することを推奨します。CFBの標準ライブラリ実装は 最適化されておらず、FIPS 140-3モジュールの一部として検証されていません。 認証されていない Stream モードが必要な場合は、代わりに NewCTR を使用してください。
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 ¶
NewCTRは、指定された Block を使用して暗号化/復号化を行う Stream を返します。 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("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
deprecated
NewOFBは、ブロック暗号bを出力フィードバックモードで使用して暗号化または復号化する Stream を返します。 初期化ベクトルivの長さは、bのブロックサイズと等しくなければなりません。
Deprecated: OFBモードは認証されておらず、一般的に平文を操作して復元するアクティブ攻撃を可能にします。 アプリケーションでは代わりに AEAD モードを使用することを推奨します。OFBの標準ライブラリ実装は 最適化されておらず、FIPS 140-3モジュールの一部として検証されていません。 認証されていない Stream モードが必要な場合は、代わりに NewCTR を使用してください。
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 ¶
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
type StreamWriter ¶
StreamWriterは Stream をio.Writerにラップします。それはXORKeyStreamを呼び出して 通過するデータの各スライスを処理します。もし StreamWriter.Write 呼び出しがshortを返す場合、 StreamWriterは同期が取れておらず、破棄する必要があります。 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を返します。