Проверка PKI на Java и Python

Я пытаюсь реализовать схему проверки PKI, где строка сообщения подписывается закрытым ключом на сервере, подпись хранится на клиенте вместе со строкой сообщения. Затем клиент проверяет подпись с помощью открытого ключа.

Ограничения моей среды: сервер — Google App Engine, а клиент — программа Java. Я играл с решениями проверки PKI только для Java и только для Python и заставил их работать, однако при выполнении одной операции на Python, а другой на Java возникает проблема, в основном из-за ограничений формата файла ключа и моего ограниченного понимания терминологии криптографии. .

Одним из самых больших ограничений является поддержка криптографии в GAE. Единственная поддерживаемая библиотека — PyCrypto, и эта библиотека не может читать открытые/закрытые ключи, хранящиеся в форматах PEM, DER или X509. Насколько я смог найти, только M2Crypto поддерживает чтение из этих файлов, но его нельзя использовать внутри GAE, потому что это оболочка вокруг openssl, а не чистое решение для Python. Даже если бы я смог найти способ перевести открытые/закрытые ключи из PEM/DER/X509 в формат, который понимает PyCrypto, это сработает для меня. Но я не мог найти способ сделать это. Есть идеи?

Я нашел одно возможное решение в виде tlslite. tlslite может прочитать закрытый ключ из файла PEM и создать подпись. Вот код.

from tlslite.utils.cryptomath import bytesToBase64
from tlslite.utils.keyfactory import parsePEMKey
s = open('private.pem').read()
key = parsePEMKey(s)

doc = 'Sample text'
bytes = array('B')
bytes.fromstring(doc)

print bytesToBase64(key.sign(bytes))

Соответствующий код Java, который я использовал для проверки подписи.

String signAlgo = "SHA1WithRSAEncryption";

// read public key from public.der
byte[] encodedKey = new byte[294];  // shortcut hardcoding
getAssets().open("public.der").read(encodedKey);

// create public key object
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey); 
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);

// read signature (created by python code above) 
byte[] encodedSig = new byte[345];
getAssets().open("signature.txt").read(encodedSig);
byte[] decodedSig = Base64.decodeBase64(encodedSig);

// Do verification
Signature verifyalg = Signature.getInstance(signAlgo);
verifyalg.initVerify(pk);
verifyalg.update(message.getBytes());
Log.d(TAG, "Verif : "+verifyalg.verify(decodedSig));

Проверка не проходит.

Я подозревал, что tlslite использует другой алгоритм для создания подписи, чем ожидает код Java.

Поэтому я попытался это выяснить.

На стороне питона

print key.getSigningAlgorithm()

дал мне

pkcs1-sha1

на стороне Java я попытался найти все поддерживаемые алгоритмы с помощью этого кода:

Set<String> algos = java.security.Security.getAlgorithms("Signature");
for(String algo : algos) {
    Log.d(TAG, algo);
}

Это дало мне

MD4WithRSAEncryption
RSASSA-PSS
SHA1withDSA
SHA1withRSA/ISO9796-2
1.2.840.113549.1.1.10
SHA512withRSA/PSS 
MD5withRSA/ISO9796-2
DSA
SHA512WithRSAEncryption
SHA224withRSA/PSS 
NONEWITHDSA
SHA256withRSA/PSS 
SHA224WithRSAEncryption
SHA256WithRSAEncryption
SHA1withRSA/PSS
SHA1WithRSAEncryption
SHA384withRSA/PSS 
SHA384WithRSAEncryption
MD5WithRSAEncryption

Я попробовал все значения SHA1 на стороне Java. Но никто не помог проверить подпись, сгенерированную tlslite, с помощью алгоритма pkcs1-sha1. Любая идея об этом отображении?


person Jayesh    schedule 08.12.2009    source источник


Ответы (2)


Это разные операции. В Python вам нужно использовать hashAndSign. По умолчанию используется хэш SHA1.

person ZZ Coder    schedule 08.12.2009
comment
Это точно! Большое спасибо. - person Jayesh; 08.12.2009

Keyczar должен нормально работать в App Engine и доступен как для Java, так и для Python.

person Nick Johnson    schedule 10.12.2009