rsa

package
v1.21.8 Latest Latest
Warning

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

Go to latest
Published: Dec 24, 2023 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package rsaは、PKCS #1およびRFC 8017で指定されたRSA暗号化を実装します。

RSAは、このパッケージで使用される単一の基本操作であり、公開鍵暗号化または公開鍵署名のいずれかを実装するために使用されます。

RSAの暗号化および署名の元となる仕様は、PKCS #1であり、デフォルトでは "RSA暗号化"および "RSA署名"という用語は、通常PKCS #1バージョン1.5を指します。ただし、その仕様には欠陥があり、新しい設計はできる限りOAEPとPSSと呼ばれるバージョン2を使用するべきです。

このパッケージには2つのセットのインタフェースが含まれています。より抽象的なインタフェースが不要な場合は、v1.5 / OAEPでの暗号化/復号化、およびv1.5 / PSSでの署名/検証のための関数があります。公開鍵原則に対して抽象化する必要がある場合は、PrivateKey型がcryptoパッケージのDecrypterおよびSignerインタフェースを実装します。

このパッケージの操作は、一部の操作を除いて、一定の時間アルゴリズムを使用して実装されています。GenerateKeyPrivateKey.Precompute、および[PrivateKey.Validate]を除くすべての他の操作は、関連する値のビットサイズのみ漏洩し、すべての値は選択したキーサイズに依存します。

Index

Examples

Constants

View Source
const (

	// PSSSaltLengthAuto は、PSS署名におけるソルトをできるだけ大きくし、検証時には自動で検出されるようにします。
	PSSSaltLengthAuto = 0

	// PSSSaltLengthEqualsHash は、署名に使用されるハッシュの長さと同じ長さのソルトを使用します。
	PSSSaltLengthEqualsHash = -1
)

Variables

View Source
var ErrDecryption = errors.New("crypto/rsa: decryption error")

ErrDecryptionはメッセージの復号に失敗したことを表します。 適応攻撃を避けるため、故意に曖昧さを持たせています。

View Source
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size")

ErrMessageTooLong は、鍵のサイズに対して大きすぎるメッセージを暗号化または署名しようとした場合に返されます。SignPSSを使用する場合、塩のサイズが大きすぎる場合にも返されることがあります。

View Source
var ErrVerification = errors.New("crypto/rsa: verification error")

ErrVerificationは署名を検証できなかったことを表します。 自己適応攻撃を避けるために、意図的にあいまいです。

Functions

func DecryptOAEP

func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)

DecryptOAEPはRSA-OAEPを使用して暗号文を復号化します。

OAEPはランダムオラクルとして使用されるハッシュ関数でパラメータ化されます。 特定のメッセージの暗号化および復号化は、同じハッシュ関数を使用する必要があります。 sha256.New()が妥当な選択肢です。

ランダムパラメータは旧式で無視され、nilであることができます。

ラベルパラメータは暗号化時に指定した値と一致する必要があります。 詳細については、EncryptOAEPを参照してください。

Example
ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
label := []byte("orders")

plaintext, err := rsa.DecryptOAEP(sha256.New(), nil, test2048Key, ciphertext, label)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
	return
}

fmt.Printf("Plaintext: %s\n", string(plaintext))

// 暗号化は機密性のみを提供することを覚えておいてください。
// メッセージが正当性を想定した前に、暗号文には署名する必要があります。さらに、メッセージは順序が変更される可能性も考慮してください。
Output:

func DecryptPKCS1v15

func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)

DecryptPKCS1v15は、RSAとPKCS #1 v1.5のパディングスキームを使用して平文を復号化します。 ランダムパラメータは旧式であり、無視されるため、nilである可能性があります。

この関数がエラーを返すかどうかによって、秘密情報が漏洩する可能性があることに注意してください。 攻撃者がこの関数を繰り返し実行させ、各インスタンスがエラーを返すかどうかを学ぶことができれば、 秘密鍵を持っているかのように復号化し、署名を偽造することができます。この問題を解決する方法として、 DecryptPKCS1v15SessionKeyを参照してください。

func DecryptPKCS1v15SessionKey

func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error

DecryptPKCS1v15SessionKeyは、RSAとPKCS #1 v1.5のパディングスキームを使用してセッションキーを復号化します。randomパラメータは旧式であり、無視されることがあります。nilでも構いません。 DecryptPKCS1v15SessionKeyは、暗号文の長さが正しくない場合や、暗号文が公開モジュラスよりも大きい場合にエラーを返します。それ以外の場合はエラーは返されません。パディングが有効な場合、結果の平文メッセージはkeyにコピーされます。そうでない場合、keyは変更されません。これらの代替は一定時間内に発生します。この関数の使用者は、事前にランダムなセッションキーを生成し、その値でプロトコルを継続することが意図されています。 セッションキーが小さすぎる場合、攻撃者による総当たり攻撃が可能になる場合があります。攻撃者がそれを行えば、ランダムな値が使用されたかどうか(同じ暗号文に対しては異なる値になるため)と、したがってパディングが正しいかどうかを学ぶことができます。これはまた、この関数の目的を阻害します。少なくとも16バイトのキーを使用することで、この攻撃に対して保護されます。 このメソッドは、RFC 3218セクション2.3.2で説明されているBleichenbacher選択暗号文攻撃[0]に対する保護を実装しています。これらの保護は、Bleichenbacher攻撃を非常に困難にしますが、保護はDecryptPKCS1v15SessionKeyを使用するプロトコルの残りの部分がこれらの考慮事項に基づいて設計されている場合にのみ効果的です。特に、復号化されたセッションキーを使用する後続の操作が、キーに関する情報(たとえば、静的なキーかランダムキーか)を漏洩させる場合、これらの緩和策は無効になります。このメソッドは非常に注意して使用する必要があり、通常は既存のプロトコル(TLSなど)との互換性のために絶対に必要な場合にのみ使用するべきです。

  • [0] “Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel Bleichenbacher, Advances in Cryptology (Crypto'98)
  • [1] RFC 3218, Preventing the Million Message Attack on CMS, https://www.rfc-editor.org/rfc/rfc3218.html
Example

RSAは非常に限られた量のデータしか暗号化できません。したがって、合理的な量のデータを暗号化するためには、一般的にハイブリッド方式が使用されます。具体的には、RSAはAES-GCMのような対称プリミティブの鍵を暗号化するために使用されます。 暗号化する前に、データは既知の構造に埋め込むことで「パディング」されます。これにはいくつかの理由がありますが、最も明らかな理由は、指数関数がモジュラスよりも大きい値になるようにするためです(そうしないと平方根で復号化できてしまいます)。 これらの設計では、PKCS #1 v1.5を使用する場合、受信したRSAメッセージが形式に適合しているか(つまり、復号化の結果が正しくパディングされたメッセージか)を漏らさないようにすることが重要です。そのためにDecryptPKCS1v15SessionKeyはこの状況に対応しており、復号化された対称鍵が適切な形式であれば、ランダムなキーを含むバッファ上で一定時間内に対称鍵をコピーします。したがって、RSAの結果が形式に適合していない場合は、実装が一定時間内にランダムなキーを使用します。

// ハイブリッド方式では、少なくとも16バイトの対称鍵を使用する必要があります。ここでは、RSA復号が正しく形成されていない場合に使用されるランダムな鍵を読み取ります。
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
	panic("RNG failure")
}

rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")

if err := rsa.DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, rsaCiphertext, key); err != nil {

	// 発生したエラーは「公開される」ものであり、秘密情報なしでも判断できます。(例えば、RSA公開鍵の長さが不可能な場合など)
	fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err)
	return
}

// 与えられたキーを使用して、対称スキームを使ってより大きな暗号文を複合することができます。
block, err := aes.NewCipher(key)
if err != nil {
	panic("aes.NewCipher failed: " + err.Error())
}

// キーがランダムであるため、固定されたNonceを使用することは許容されます。
// (キー、Nonce)のペアは依然として一意である必要があります。
var zeroNonce [12]byte
aead, err := cipher.NewGCM(block)
if err != nil {
	panic("cipher.NewGCM failed: " + err.Error())
}
ciphertext, _ := hex.DecodeString("00112233445566")
plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil)
if err != nil {

	// RSAの暗号文の形式が不正です。AES-GCMの鍵が正しくないため、復号化はここで失敗します。
	fmt.Fprintf(os.Stderr, "Error decrypting: %s\n", err)
	return
}

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

func EncryptOAEP

func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error)

EncryptOAEPはRSA-OAEPで与えられたメッセージを暗号化します。

OAEPはランダムオラクルとして使用されるハッシュ関数でパラメータ化されています。 暗号化と復号化は同じハッシュ関数を使用する必要があります。 sha256.New()は妥当な選択肢です。

ランダムパラメータはエントロピーのソースとして使用され、同じメッセージを2回暗号化しても 同じ暗号文にならないようにします。 ほとんどのアプリケーションでは、[crypto/rand.Reader]をランダムとして使用するべきです。

ラベルパラメータには暗号化されない任意のデータを含めることができます。 ただし、このデータはメッセージに重要な文脈を与えます。 例えば、特定の公開鍵が2つのタイプのメッセージを暗号化する場合、異なるラベル値を使用して 攻撃者が別の目的で暗号文を使用できないようにすることができます。 必要ない場合は空にしても構いません。

メッセージは公開モジュラスの長さからハッシュの2倍の長さを引いた値より長くすることはできません。 さらに2を引いた長さ以下である必要があります。

Example
secretMessage := []byte("send reinforcements, we're going to advance")
label := []byte("orders")

// crypto/rand.Readerは暗号化関数のランダム化において十分なエントロピー源です。
rng := rand.Reader

ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
	return
}

// 暗号化はランダムな関数のため、暗号文は毎回異なるものとなります。
fmt.Printf("Ciphertext: %x\n", ciphertext)
Output:

func EncryptPKCS1v15

func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error)

EncryptPKCS1v15は、与えられたメッセージをRSAとPKCS #1 v1.5のパディングスキームで暗号化します。メッセージの長さは、公開モジュラスの11バイトを引いた長さ以下である必要があります。 ランダムパラメータはエントロピーソースとして使用され、同じメッセージを2回暗号化しても同じ暗号文が生成されないようにします。ほとんどのアプリケーションでは、[crypto/rand.Reader]をランダム関数として使用することが推奨されます。ただし、返される暗号文はランダムから読み取られたバイトに対して決定論的に依存せず、呼び出しやバージョンによって変わる場合があります。 注意:セッションキー以外の平文を暗号化するためにこの関数を使用することは危険です。新しいプロトコルではRSA OAEPを使用してください。

func SignPKCS1v15

func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)

SignPKCS1v15は、RSASSA-PKCS1-V1_5-SIGNを使用して、ハッシュされたデータの署名を計算します。ハッシュされたデータは、与えられたハッシュ関数を使用して入力メッセージをハッシュした結果でなければなりません。ハッシュがゼロの場合は、ハッシュされたデータが直接署名されます。これは相互運用性のためにのみ推奨されません。 randomパラメータはレガシーであり、無視されることがあります。nilにすることもできます。 この関数は決定的です。したがって、可能なメッセージのセットが小さい場合、攻撃者はメッセージから署名へのマップを作成し、署名されたメッセージを特定する可能性があります。いつものように、署名は真正さを提供し、機密性は提供しません。

Example
message := []byte("message to be signed")

// 直接署名できるのは小さなメッセージだけです。そのため、メッセージ自体ではなくそのハッシュを署名します。これにはハッシュ関数が衝突耐性がある必要があります。SHA-256は、執筆時点(2016年)では最も弱いハッシュ関数です。
hashed := sha256.Sum256(message)

signature, err := rsa.SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA256, hashed[:])
if err != nil {
	fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
	return
}

fmt.Printf("Signature: %x\n", signature)
Output:

func SignPSS added in v1.2.0

func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error)

SignPSSはPSSを使用してダイジェストの署名を計算します。

ダイジェストは、指定されたハッシュ関数を使用して入力メッセージをハッシュすることによって得られた結果である必要があります。 opts引数は、nilの場合、適切なデフォルト値が使用されます。opts.Hashが設定されている場合は、hashが上書きされます。

署名は、メッセージ、キー、およびソルトサイズに応じてランダム化され、ランドからのバイトを使用します。 ほとんどのアプリケーションでは、[crypto/rand.Reader]をrandとして使用するべきです。

func VerifyPKCS1v15

func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error

VerifyPKCS1v15は、RSA PKCS #1 v1.5の署名を検証します。 hashedは、入力メッセージを指定されたハッシュ関数でハッシュ化した結果で、 sigは署名です。有効な署名の場合、nilエラーが返されます。 hashがゼロであれば、hashedは直接使用されます。 これは相互運用性以外の用途には適していません。

Example
message := []byte("message to be signed")
signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")

// 直接署名できるのは小さなメッセージのみです。そのため、メッセージ自体ではなく、メッセージのハッシュが署名されます。これには、ハッシュ関数が衝突耐性を持つ必要があります。SHA-256は、書かれた時点(2016年)で使用すべき最も安全なハッシュ関数です。
hashed := sha256.Sum256(message)

err := rsa.VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature)
if err != nil {
	fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
	return
}

// シグネチャは公開鍵からのメッセージの有効な署名です。
Output:

func VerifyPSS added in v1.2.0

func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error

VerifyPSSはPSS署名を検証します。

エラーがnilである場合、有効な署名です。ダイジェストは入力メッセージを与えられたハッシュ関数を使用してハッシュした結果である必要があります。opts引数はnilである場合、適切なデフォルト値が使用されます。opts.Hashは無視されます。

Types

type CRTValue

type CRTValue struct {
	Exp   *big.Int
	Coeff *big.Int
	R     *big.Int
}

CRTValueには事前計算された中国剰余定理の値が含まれています。

type OAEPOptions added in v1.5.0

type OAEPOptions struct {
	// Hashはマスク生成時に使用されるハッシュ関数です。
	Hash crypto.Hash

	// MGFHashはMGF1で使用されるハッシュ関数です。
	// ゼロの場合、代わりにHashが使用されます。
	MGFHash crypto.Hash

	// ラベルは、暗号化の際に使用される値と等しい任意のバイトストリングです。
	Label []byte
}

OAEPOptionsは、crypto.Decrypterインタフェースを使用してOAEP復号化にオプションを渡すためのインタフェースです。

type PKCS1v15DecryptOptions added in v1.5.0

type PKCS1v15DecryptOptions struct {

	// SessionKeyLenは、復号化されているセッションキーの長さです。
	// ゼロでない場合、復号化中のパディングエラーにより、エラーが返される代わりに、この長さのランダムな平文が返されます。
	// これらの代替は一定の時間で発生します。
	SessionKeyLen int
}

PKCS1v15DecryptOptionsは、crypto.Decrypterインターフェースを使用してPKCS #1 v1.5復号化にオプションを渡すためのものです。

type PSSOptions added in v1.2.0

type PSSOptions struct {

	// SaltLengthはPSS署名で使用されるソルトの長さを制御します。
	// それはバイト数の正数であるか、または特別なPSSSaltLengthの定数のいずれかです。
	SaltLength int

	// Hashはメッセージダイジェストを生成するために使用されるハッシュ関数です。ゼロでない場合、SignPSSに渡されたハッシュ関数を上書きします。PrivateKey.Signを使用する場合には必須です。
	Hash crypto.Hash
}

PSSOptionsはPSS署名の作成と検証のためのオプションを含んでいます。

func (*PSSOptions) HashFunc added in v1.4.0

func (opts *PSSOptions) HashFunc() crypto.Hash

HashFunc は opts.Hash を返します。これにより、PSSOptions は crypto.SignerOpts を実装します。

type PrecomputedValues

type PrecomputedValues struct {
	Dp, Dq *big.Int
	Qinv   *big.Int

	// CRTValuesは3番目以降の素数に使用されます。歴史的な偶然により、
	// 最初の2つの素数のためのCRTはPKCS #1で異なる方法で処理されますが、
	// この相互運用性は十分に重要です。
	//
	// 廃止予定:これらの値は、後方互換性のためにまだPrecomputeによって
	// 埋められていますが、使用されていません。マルチプライムRSAは非常に稀ですが、
	// 複雑さを制限するためにこのパッケージでCRTの最適化なしで実装されています。
	CRTValues []CRTValue
	// contains filtered or unexported fields
}

type PrivateKey

type PrivateKey struct {
	PublicKey
	D      *big.Int
	Primes []*big.Int

	// PrecomputedはRSAの操作を高速化するために事前計算された値を含んでいます。
	// 利用可能な場合は、PrivateKey.Precomputeを呼び出して生成されなければなりません。
	// また、変更してはいけません。
	Precomputed PrecomputedValues
}

PrivateKeyはRSAキーを表します

func GenerateKey

func GenerateKey(random io.Reader, bits int) (*PrivateKey, error)

GenerateKeyは指定されたビットサイズのランダムなRSA秘密鍵を生成します。

ほとんどのアプリケーションはrandとして[crypto/rand.Reader]を使用するべきです。注意:返される鍵は、randから読み取られたバイトに従属的に決定されず、呼び出しやバージョンによって変わる可能性があります。

func GenerateMultiPrimeKey deprecated

func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error)

GenerateMultiPrimeKeyは指定されたビットサイズとランダムソースで、マルチプライムRSA鍵ペアを生成します。

"On the Security of Multi-prime RSA"のテーブル1には、与えられたビットサイズの最大プライム数が示されています。

公開鍵は2つのプライムの場合と互換性がありますが、秘密鍵は異なります。したがって、特定の形式でマルチプライムの秘密鍵をエクスポートしたり、他のコードに後からインポートすることができない場合があります。

このパッケージではマルチプライムRSAのCRT最適化を実装していないため、2つ以上のプライムを持つキーのパフォーマンスは悪くなります。

Deprecated: 上記のセキュリティ、互換性、およびパフォーマンスの理由により、2つ以外のプライム数でこの関数を使用することはお勧めしません。代わりにGenerateKeyを使用してください。

func (*PrivateKey) Decrypt added in v1.5.0

func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error)

Decryptはprivで暗号文を復号化します。optsがnilまたは*PKCS1v15DecryptOptions型の場合、PKCS #1 v1.5 復号化が実行されます。それ以外の場合、optsは*OAEPOptions型でなければなりませんし、OAEP 復号化が行われます。

func (*PrivateKey) Equal added in v1.15.0

func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool

Equalはprivとxが等価な値を持つかどうかを報告します。事前計算された値は無視されます。

func (*PrivateKey) Precompute

func (priv *PrivateKey) Precompute()

Precomputeは未来の秘密鍵操作を高速化するためのいくつかの計算を実行します。

func (*PrivateKey) Public added in v1.4.0

func (priv *PrivateKey) Public() crypto.PublicKey

Publicはprivに対応する公開鍵を返します。

func (*PrivateKey) Sign added in v1.4.0

func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)

privという秘密鍵を使用して、乱数をrandから読み取り、署名digestを生成します。optsが*PSSOptionsの場合、PSSアルゴリズムが使用されます。それ以外の場合は、PKCS #1 v1.5が使用されます。digestは、opts.HashFunc()を使用して入力メッセージのハッシュ値を計算した結果でなければなりません。 このメソッドはcrypto.Signerを実装しており、例えばハードウェアモジュールに保持される秘密部分をサポートするインターフェースです。一般的な使用法では、このパッケージ内のSign*関数を直接使用するべきです。

func (*PrivateKey) Validate

func (priv *PrivateKey) Validate() error

Validateはキーに基本的な正当性チェックを行います。 キーが正当であれば、nilを返します。それ以外の場合は、問題を説明するエラーが返されます。

type PublicKey

type PublicKey struct {
	N *big.Int
	E int
}

func (*PublicKey) Equal added in v1.15.0

func (pub *PublicKey) Equal(x crypto.PublicKey) bool

Equalは、pubとxが同じ値を持っているかどうかを報告します。

func (*PublicKey) Size added in v1.11.0

func (pub *PublicKey) Size() int

Size はバイト単位での剰余サイズを返します。この公開鍵による生の署名および暗号文のサイズは同じです。

Jump to

Keyboard shortcuts

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