...

パッケージ rsa

import "crypto/rsa"
概要
目次

概要 ▾

rsa パッケージは,PKCS#1 で定義された RSA 暗号を実装します。

RSA は,このパッケージで公開鍵暗号化または公開鍵署名を実装するために使用される 1 つの基本的な操作です。

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

このパッケージには, 2 セットのインターフェースが含まれています。 より抽象的なインターフェースが不要な場合は, v1.5/OAEP で暗号化 / 復号化したり, v1.5/PSS で署名 / 検証するための関数があります。 公開鍵プリミティブを介して抽象化する必要がある場合, PrivateKey 構造体はcryptoパッケージの Decrypter と Signer インターフェースを実装します。

このパッケージの RSA 操作は,一定時間アルゴリズムを使用して実装されていません。

目次 ▾

定数
変数
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error)
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error)
func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error
func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error
type CRTValue
type OAEPOptions
type PKCS1v15DecryptOptions
type PSSOptions
    func (pssOpts *PSSOptions) HashFunc() crypto.Hash
type PrecomputedValues
type PrivateKey
    func GenerateKey(random io.Reader, bits int) (*PrivateKey, error)
    func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error)
    func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error)
    func (priv *PrivateKey) Precompute()
    func (priv *PrivateKey) Public() crypto.PublicKey
    func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
    func (priv *PrivateKey) Validate() error
type PublicKey
    func (pub *PublicKey) Size() int

パッケージファイル

pkcs1v15.go pss.go rsa.go

定数

const (
    // PSSSaltLengthAuto は, PSS 署名のソルトを署名時にはできるだけ大きくし,検証時には自動的に検出されるようにします。
    PSSSaltLengthAuto = 0
    // PSSSaltLengthEqualsHash により, salt の長さは署名に使用されているハッシュの長さと等しくなります。
    PSSSaltLengthEqualsHash = -1
)

変数

ErrDecryption はメッセージの復号化の失敗を表します。 適応攻撃を避けるため,これは意図的に曖昧になっています。

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

公開鍵のサイズに対して大きすぎるメッセージを暗号化しようとすると, ErrMessageTooLong が返されます。

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

ErrVerification は署名の検証に失敗したことを表します。 適応攻撃を避けるため,これは意図的に曖昧になっています。

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

func DecryptOAEP

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

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

OAEP は,ランダムオラクルとして使用されるハッシュ関数によってパラメータ化されます。 与えられたメッセージの暗号化と復号化は同じハッシュ関数を使用しなければならず, sha256.New() は合理的な選択です。

random パラメータが nil でなければ,秘密鍵操作をブライドにし,サイドチャンネル攻撃のタイミングを避けるために使用されます。 ブラインドは純粋にこの関数の内部にあります - ランダムデータは暗号化時に使われたものと一致する必要はありません。

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

コード:

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

// RSA 操作を盲目にするための crypto/rand.Reader はエントロピーの良い情報源です。
rng := rand.Reader

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

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

// 暗号化は機密性を提供するだけであることを忘れないでください。
// 暗号文は,信憑性が想定される前に署名されるべきであり,なおかつ,メッセージが並べ替えられる可能性があることを考慮する必要があります。

func DecryptPKCS1v15

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

DecryptPKCS1v15 は, RSA と PKCS#1 v1.5 のパディング方式を使用して平文を復号化します。 rand != nil の場合,サイドチャンネル攻撃のタイミングを回避するために RSA ブラインディングを使用します。

この関数がエラーを返すかどうかは,機密情報を開示することに注意してください。 攻撃者がこの関数を繰り返し実行し,各インスタンスがエラーを返したかどうかを知ることができる場合,秘密キーを持っているかのようにシグニチャを復号化して偽造することができます。 この問題を解決する方法については DecryptPKCS1v15SessionKey を参照してください。

func DecryptPKCS1v15SessionKey

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

DecryptPKCS1v15SessionKey は, RSA と PKCS#1 v1.5 のパディング方式を使用してセッションキーを復号化します。 rand != nil の場合,サイドチャンネル攻撃のタイミングを回避するために RSA ブラインディングを使用します。 暗号文の長さが間違っている場合,または暗号文がパブリックモジュラスより大きい場合はエラーを返します。 それ以外の場合,エラーは返されません。 パディングが有効な場合,結果の平文メッセージは key にコピーされます。 それ以外の場合,キーは変わりません。 これらの選択肢は一定時間内に発生します。 この関数のユーザは事前にランダムセッションキーを生成し,その結果の値でプロトコルを継続することを意図しています。 これにより,攻撃者がプレーンテキストに関する情報を習得する可能性がなくなります。 Daniel Bleichenbacher の "RSA 暗号化規格 PKCS#1 に基づくプロトコルに対する暗号化された暗号化攻撃 "(Crypto'98) を参照してください。

セッションキーが小さすぎると,攻撃者がそれをブルートフォースする可能性があることに注意してください。 それが可能であれば,(同じ暗号文ではランダム値が異なるため)ランダムな値が使用されているかどうかを知ることができ,故にパディングが正しいかどうかを知ることができます。 これはこの機能のポイントを破ります。 少なくとも 16 バイトのキーを使用すると,この攻撃から保護されます。

RSA は非常に限られた量のデータだけを暗号化することができます。 合理的な量のデータを暗号化するために,ハイブリッド方式が一般的に使用されます。 RSA は, AES-GCM のような対称プリミティブのための鍵を暗号化するために使用されます。 暗号化の前に,データはそれを既知の構造に埋め込むことによって " パディング " されます。 これにはいくつかの理由がありますが,最も明白なのは,べき乗がべき乗よりも大きくなるように値が十分に大きいことを確認することです。 (それ以外の場合は,平方根で復号化される可能性があります。) これらの設計では, PKCS#1 v1.5 を使用するとき,受信した RSA メッセージが整形されたかどうか (つまり,復号化の結果が正しくパディングされたメッセージであるかどうか) の開示を避けることが極めて重要です, なぜならこれが秘密の情報を漏らすからです。 DecryptPKCS1v15SessionKey はこのような状況に対応するように設計されており, (整形されている場合)復号化された対称鍵 をランダム鍵を含むバッファーに一定時間でコピーします。 したがって, RSA の結果が整形されてない場合,実装は一定時間内にランダムキーを使用します。

コード:

// RSA 操作を盲目にするための crypto/rand.Reader はエントロピーの良い情報源です。
rng := rand.Reader

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

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

if err := DecryptPKCS1v15SessionKey(rng, 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())
}

// 鍵はランダムであるため, (key, 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))

func EncryptOAEP

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

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

OAEP は,ランダムオラクルとして使用されるハッシュ関数によってパラメータ化されます。 与えられたメッセージの暗号化と復号化は同じハッシュ関数を使用しなければならず, sha256.New() は合理的な選択です。

random パラメータは,同じメッセージを 2 回暗号化しても同じ暗号文が生成されないようにするためのエントロピーの元として使用されます。

label パラメータには,暗号化されない任意のデータを含めることができますが,これはメッセージに重要なコンテキストを与えます。 例えば,与えられた公開鍵が 2 つの型のメッセージを解読するために使用されるならば,ある目的のための暗号文が攻撃者によって別の目的のために使用されないことを確実にするために異なるラベル値が使用され得ます。 必要でなければ空にすることができます。

メッセージは,パブリックモジュラスの長さからハッシュ長の 2 倍を引いたもの,さらに 2 を引いたもの以下でなければなりません。

コード:

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

// crypto/rand.Reader は,暗号化関数をランダム化するための優れたエントロピー源です。
rng := rand.Reader

ciphertext, err := 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)

func EncryptPKCS1v15

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

EncryptPKCS1v15 は, RSA と PKCS#1 v1.5 のパディング方式を使用して,指定されたメッセージを暗号化します。 メッセージは,パブリックモジュラスの長さから 11 バイトを引いた長さを超えてはいけません。

rand パラメータは,同じメッセージを 2 回暗号化しても同じ暗号文が生成されないようにするためのエントロピーのソースとして使用されます。

警告 : セッションキー以外の平文を暗号化するためにこの関数を使用することは危険です。 新しいプロトコルで RSA OAEP を使用してください。

func SignPKCS1v15

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

SignPKCS1v15 は, RSA PKCS#1 v1.5 の RSASSA-PKCS1-V1_5-SIGN を使用してハッシュの署名を計算します。 hashed は与えられたハッシュ関数を使って入力メッセージをハッシュした結果でなければならないことに注意してください。 hash がゼロの場合,hashedが直接署名されます。 これは相互運用性のため以外にはお勧めできません。

rand が nil でない場合は,サイドチャンネル攻撃のタイミングを回避するために RSA ブラインディングが使用されます。

この関数は決定論的です。 したがって,可能性のあるメッセージのセットが小さい場合,攻撃者はメッセージから署名へのマップを作成し,署名されたメッセージを特定する可能性があります。 これまでと同様に,署名は機密性ではなく信頼性を提供します。

コード:

// RSA 操作を盲目にするための crypto/rand.Reader はエントロピーの良い情報源です。
rng := rand.Reader

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

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

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

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

func SignPSS 1.2

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

SignPSS は RSASSA-PSS [1] を使用してhashedの署名を計算します。 hashed は与えられたハッシュ関数を使って入力メッセージをハッシュした結果でなければならないことに注意してください。 opts 引数は nil でも構いません。 その場合は賢明なデフォルトが使用されます。

func VerifyPKCS1v15

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

VerifyPKCS1v15 は RSA PKCS#1 v1.5 の署名を検証します。 hashed は与えられたハッシュ関数を使って入力メッセージをハッシュした結果で, sig は署名です。 有効なシグニチャは nil エラーを返すことによって示されます。 hash が 0 の場合,hashedが直接使われます。 これは相互運用性のため以外にはお勧めできません。

コード:

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

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

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

// signatureは公開鍵からのメッセージの有効な署名です。

func VerifyPSS 1.2

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

VerifyPSS は PSS の署名を検証します。 hashed は与えられたハッシュ関数を使って入力メッセージをハッシュした結果で, sig は署名です。 有効なシグニチャは nil エラーを返すことによって示されます。 opts 引数は nil でも構いません。 その場合は賢明なデフォルトが使用されます。

type CRTValue

CRTValue は事前計算された中国の剰余定理値を含みます。

type CRTValue struct {
    Exp   *big.Int // D mod (prime-1) 。
    Coeff *big.Int // R·Coeff ≡ 1 mod Prime 。
    R     *big.Int // これより前の素数の積 (inc p と q) 。
}

type OAEPOptions 1.5

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

type OAEPOptions struct {
    // Hashは,マスクを生成するときに使用されるハッシュ関数です。
    Hash crypto.Hash
    // Labelは,暗号化時に使用された値と等しくなければならない任意のバイト文字列です。
    Label []byte
}

type PKCS1v15DecryptOptions 1.5

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

type PKCS1v15DecryptOptions struct {
    // SessionKeyLen は,復号化されているセッションキーの長さです。
    // 0 でなければ,復号化中のパディングエラーはエラーではなくこの長さのランダムな平文を返します。
    // これらの選択肢は一定時間内に発生します。
    SessionKeyLen int
}

type PSSOptions 1.2

PSSOptions には, PSS 署名を作成および検証するためのオプションが含まれています。

type PSSOptions struct {
    // SaltLength は, PSS 署名で使用されるソルトの長さを制御します。
    // バイト数,または特別な PSSSaltLength 定数のいずれかになります。
    SaltLength int

    // Hash がゼロでない場合, SignPSS に渡されたハッシュ関数をオーバーライドします。
    // これが crypto.Signer インターフェースを使用するときにハッシュ関数を指定する唯一の方法です。
    Hash crypto.Hash // Go 1.4
}

func (*PSSOptions) HashFunc 1.4

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

PSSOptions が crypto.SignerOpts を実装するように, HashFunc は pssOpts.Hash を返します。

type PrecomputedValues

type PrecomputedValues struct {
    Dp, Dq *big.Int // D mod (P-1) (または mod Q-1)
    Qinv   *big.Int // Q^-1 mod P

    // CRTValues は 3 回目以降の素数に使用されます。
    // 歴史的理由で,最初の 2 つの素数の CRT は PKCS#1 では異なる方法で処理されます。
    // 相互運用性のためにそれを反映する必要があります。
    CRTValues []CRTValue
}

type PrivateKey

PrivateKey は RSA キーを表します

type PrivateKey struct {
    PublicKey            // パブリック部
    D         *big.Int   // プライベート指数
    Primes    []*big.Int // N の素因数で, >= 2 の要素を持ちます。

    // Precomputed には,可能であれば,プライベート操作を高速化する事前計算値が含まれています。
    Precomputed PrecomputedValues
}

func GenerateKey

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

GenerateKey は,ランダムソース random (たとえば, crypto/rand.Reader) を使用して,指定されたビットサイズの RSA キーペアを生成します 。

func GenerateMultiPrimeKey

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

GenerateMultiPrimeKey は,[1] で示唆されているように, 与えられたビットサイズと与えられたランダムソースのマルチプライム RSA 鍵ペアを生成します。 公開鍵は 2 素数の場合と互換性がありますが (実際には区別できません) ,秘密鍵は互換性がありません。 したがって,マルチプライム秘密鍵を特定の形式でエクスポートしたり,後で他のコードにインポートしたりすることは不可能な場合があります。

[2] の表 1 は,与えられたサイズに対する素数の最大数を示しています。

[1] 米国特許 4405829 (1972 年,期限切れ) [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf

func (*PrivateKey) Decrypt 1.5

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) Precompute

func (priv *PrivateKey) Precompute()

Precompute (事前計算) は,将来的に秘密鍵操作を高速化する計算をいくつか実行します。

func (*PrivateKey) Public 1.4

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

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

func (*PrivateKey) Sign 1.4

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

Sign は, rand からランダム性を読み取って priv でダイジェストします。 opts が *PSSOptions の場合は PSS アルゴリズムが使用され,それ以外の場合は PKCS#1 v1.5 が使用されます。

このメソッドは crypto.Signer を実装します。 これは,秘密部分がハードウェアモジュールなどに保存されている場合にキーをサポートするためのインターフェースです。 一般的な用途では,このパッケージの Sign* 関数を直接使用してください。

func (*PrivateKey) Validate

func (priv *PrivateKey) Validate() error

Validate はキーに対して基本的な健全性チェックを実行します。 キーが有効な場合は nil を返し,そうでない場合は問題を説明するエラーを返します。

type PublicKey

PublicKey は RSA キーの公開部分を表します。

type PublicKey struct {
    N *big.Int // 法
    E int      // 公開指数
}

func (*PublicKey) Size 1.11

func (pub *PublicKey) Size() int

Size はモジュラスサイズをバイト単位で返します。 この公開鍵のための,またはこの公開鍵による生の署名と暗号文は,同じサイズになります。