Почему для функции Go EncryptOAEP в библиотеке crypto / rsa требуется случайный io.Reader?

#encryption #tcp #go #cryptography #rsa

#шифрование #tcp #Вперед #криптография #rsa

Вопрос:

Я пишу файловый сервер, который шифрует данные на стороне клиента, отправляет данные по протоколу TCP и расшифровывает их на стороне сервера, используя асимметричное шифрование RSA-OAEP. Есть две основные функции, которые я пытался использовать, которые принимают следующие аргументы в документации:

 EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error)
DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error)
  

Для каждого требуется random io.Reader , а тестовый файл использует rand.Reader из crypto / rand. Однако всякий раз, когда я шифрую сообщение с rand.Reader помощью на стороне клиента, сообщение никогда не расшифровывается должным образом на стороне сервера, у которого есть отдельный экземпляр rand.Reader .

  1. Какова цель random io.Reader ?
  2. Как я могу гарантировать, что зашифрованное сообщение будет передано и расшифровано сервером должным образом? Нужно ли мне также передавать некоторую информацию об rand.Reader используемом клиентом сервере, чтобы сообщение было правильно расшифровано?

Комментарии:

1. Функция шифрования , требующая источника случайности, довольно очевидна, OAEP определяется как рандомизированное дополнение (иначе шифрование одного и того же открытого текста всегда приводило бы к одному и тому же зашифрованному тексту, утечке информации). Случайность во время дешифрования используется только для ослепления / защиты от временных атак и не должна влиять на результат.

2. С другой стороны, рассмотрите возможность использования TLS вместо создания собственного протокола. Есть много деталей, которые можно ошибиться, включая аутентификацию сервера, прямую секретность, повторные атаки, заполнение оракулов,…

3. Можете ли вы опубликовать больше своего кода? Я подозреваю, что фактическая ошибка заключается в чем-то совершенно другом. Возможно, что-то связанное с кодированием или обработкой TCP как последовательности сообщений вместо потока, чтобы назвать две распространенные ошибки. Чтобы отладить его самостоятельно, сбросьте необработанные байты, которые вы извлекаете, EncryptOAEP и необработанные байты, которые вы передаете DecryptOAEP , чтобы увидеть, отличаются ли они по длине или содержанию.

Ответ №1:

Используя rsa_test.go в качестве основы, мне удалось создать небольшую сквозную программу дешифрования. Из предоставленной вами информации трудно определить, где ошибка, но я надеюсь, что, прочитав эту программу, вы сможете найти ошибку самостоятельно. Вероятно, вам не нужно предоставлять Reader в DecryptOAEP.

http://play.golang.org/p/7VVCHJOB7R

 package main

import (
    "bytes"
    "crypto/rsa"
    "crypto/sha1"
    "log"
    "math/big"
)

func main() {
    sha1 := sha1.New()
    n := new(big.Int)
    d := new(big.Int)

    rsa_modulus := "a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb"
    rsa_d := "53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"

    n.SetString(rsa_modulus, 16)
    d.SetString(rsa_d, 16)
    public := rsa.PublicKey{n, 65537}
    d.SetString(rsa_d, 16)
    private := new(rsa.PrivateKey)
    private.PublicKey = public
    private.D = d

    seed := []byte{0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69,
        0x77, 0x6a, 0x33, 0xe9, 0x6b, 0xad, 0x48, 0xe1, 0xdd,
        0xa0, 0xa5, 0xef,
    }
    randomSource := bytes.NewReader(seed)

    in := []byte("Hello World")

    encrypted, err := rsa.EncryptOAEP(sha1, randomSource, amp;public, in, nil)
    if err != nil {
        log.Println("error: %s", err)
    }

    plain, err := rsa.DecryptOAEP(sha1, nil, private, encrypted, nil)
    if err != nil {
        log.Println("error: %s", err)
    }

    log.Println(string(plain))
}
  

Комментарии:

1. Согласно документам, вам не нужно предоставлять random to DecryptOAEP , но вы должны сделать это для защиты от атак по побочным каналам.