WinAPI -> CryptoAPI -> RSA, шифровать приватным, расшифровывать при помощи общедоступного

Добрый день.

Мне нужно научить Windows CryptoAPI шифровать сообщение приватной (не публичной) частью ключа, а расшифровывать при помощи публичной. Это необходимо для предоставления пользователям информации, которую они могут прочитать, но не могут изменить.

Как это работает сейчас:

я понимаю контекст

CryptAcquireContext(@Prov, PAnsiChar(containerName), nil, PROV_RSA_FULL, 0)

сгенерировать пару ключей

CryptGenKey(Prov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, @key)

Зашифровать (и тут проблема. "ключ" - ключевая пара, и функция использует ее публичную часть);

CryptEncrypt(key, 0, true, 0, @res[1], @strLen, buffSize)

Расшифровать (здесь та же проблема, используется закрытая часть ключа)

CryptDecrypt(key, 0, true, 0, @res[1], @buffSize)

Спасибо за внимание/помощь.

Обновить

Да, я мог бы использовать цифровую подпись и другие методы...

Проблема в том, что мне нужно зашифровать одно поле базы данных и сделать так, чтобы никто, кроме меня, не смог его изменить. Прочитать это поле можно будет только с помощью моей программы (пока ее кто-нибудь не декомпилирует и не получит публичный ключ). Это можно сделать с помощью симметричного ключа и цифровых подписей, но тогда мне нужно будет создать другое поле и сохранить другой ключ и так далее...

Я очень надеюсь, что мы сможем как-то научить WIN API делать то, что я хочу. Я знаю, что могу сделать это с помощью RSA, и я надеюсь, что WinAPI каким-то образом поддерживает эту функцию.


person TheHorse    schedule 11.06.2012    source источник


Ответы (2)


Шифрование данных с помощью закрытого ключа и расшифровка их с помощью открытого ключа не поддерживаются, поскольку любой, у кого есть «опубликованный» открытый ключ, может расшифровать их. Какой тогда смысл в шифровании?

Если вы хотите убедиться, что данные не были изменены, вместо этого вы захотите подписать данные. Подписание шифрует хэш данных с помощью закрытого ключа. Посмотрите на функции подписи.

Возможно, вы сможете обмануть функции подписи, чтобы они делали то, что вы хотите. Я делал это с другими реализациями, но не пробовал с Microsoft CryptoAPI.

Также обратите внимание, что при шифровании RSA обычное текстовое сообщение не может быть длиннее ключа. Таким образом, если вы используете 2048-битный ключ, вы можете зашифровать только тело сообщения размером до 256 байт (минус несколько накладных расходов).

Рассмотрите возможность использования асимметричного шифрования только для передачи симметричного ключа и используйте симметричный ключ для шифрования и дешифрования данных любого размера.

Обновить

Вы можете использовать функцию CryptSignHash(). за это. Обычно это используется для «подписания» хэша, но вы можете поместить в хеш любые данные:

Задайте хеш-значение в хэш-объекте, используя значение HP_HASHVAL параметра dwParam в CryptSetHashParam.

Вы можете быть ограничены таким количеством байтов, если ожидается, что ввод будет хэш-значением SHA1.

В качестве альтернативы вы можете рассмотреть возможность использования OpenSSL. Если я правильно помню, довольно просто использовать его функции подписи RSA для шифрования с закрытым ключом.

Кроме того, я сделал то же самое, используя старую (бесплатную) версию SecureBlackbox. Возможно, вы сможете найти старую бесплатную версию, но она не поддерживает Unicode, поэтому вам придется выполнить некоторое преобразование, если вы используете новый Delphi. Я делал это и в прошлом, так что это не слишком сложно.

Вы также можете попробовать текущую версию SecureBlackbox и приобрести ее, если она вам подходит.

В противном случае, как вы сказали, подпишите его, чтобы обнаружить подделку, и зашифруйте его с помощью симметричного ключа, который знает только программа, чтобы скрыть его.

Если они взломают ваш код, в любом случае все будет в порядке.

person Marcus Adams    schedule 11.06.2012

Строго говоря, при "подписывании" сообщения:

  • человек с закрытым ключом расшифровывает хэш своим закрытым ключом.
  • затем они отправляют этот "расшифрованный" хэш вместе с сообщением.
  • затем получатель шифрует подпись с помощью открытого ключа

Если "зашифрованный" хэш совпадает с хэшем исходного сообщения, вы знаете, что сообщение не было изменено и было отправлено человеком с закрытым ключом. Следующий псевдокод представляет алгоритм подписи:

//Person with private key generating message and signature
originalHash = GenerateHashOfMessage(message);
signature = RsaDecrypt(originalHash, privateKey);

//Receiver validating signed message
hash = GenerateHashOfMessage(message);
originalHash = RsaEncrypt(signature, publicKey);
messageValid = (hash == originalHash);

Этот же механизм можно использовать для достижения желаемого. За исключением того, что вам не нужны хэши, вы просто хотите зашифровать некоторый (небольшой) объем данных:

//Person with private key
cipherText = RsaDecrypt(plainText, privateKey);

//Person with public key
plainText = RsaEncrypt(cipherText, publicKey);

я оставлю вызовы CryptoAPI в качестве упражнения, так как я все еще пытаюсь понять Microsoft Crypto API.

person Ian Boyd    schedule 17.10.2012