Unable to verify signature in Java signed using Python - python

Stuck at this point for last few days. A file is signed in python using pss(RSA) approach.
Below is the link for reference:
https://pycryptodome.readthedocs.io/en/latest/src/signature/pkcs1_pss.html
At Java client side, while verification, below mentioned approach is used:
https://pycryptodome.readthedocs.io/en/latest/src/faq.html#are-rsassa-pss-signatures-compatible-with-java-or-openssl
Signing Approach:
A hash value has been generated from the payload and the hash value is signed using pem private key. The signature bytes are then encoded to Base64 and sent to client for verification.
Verification Approach:
Initially, a hash value is generated from the payload and then the signature bytes as received from the server side is decoded from Base64 and used for verification.
Both the hash values, viz, sent from Server side and generated at Client side, both are same. However, still the signature is unable to be verified.
Code snippet:
Signing in python:
def sign_file(rsa, byte_buffer):
mgf = lambda x, y: pss.MGF1(x, y, SHA256)
h = SHA256.new(byte_buffer.getbuffer())
print("Hash value: " ,h.hexdigest())
signer = pss.new(rsa, mask_func=mgf, salt_bytes=len(h.digest()))
print("Salt length: ", signer._saltLen)
signature = b64encode(signer.sign(h))
return signature
# SIGN
rsa_key = get_key(priv_key_file)
signature = sign_file(rsa_key, encrypted)
Verification in Java:
public static String verify(String signedData, String signedHash, boolean debug, PublicKey publickey) {
boolean successFlg = false;
try {
Security.addProvider(new BouncyCastleProvider());
Signature ss = Signature.getInstance("SHA256withRSA/PSS");
AlgorithmParameters pss1 = ss.getParameters();
PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 32, 1);
ss.setParameter(pssParameterSpec);
ss.initVerify(publickey);
ss.update(signedHash.getBytes());
successFlg = ss.verify(Base64.getDecoder().decode(signedData.getBytes()));
if (debug) {
System.out.println( "signature matched: " + successFlg);
}
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(successFlg);
}
Salt length: 32
Generated hash value:
7ff8ce3dab21c615764682394c07fbc858a5713002f68c1fce520a3a93adbecd
Signed Data(as received from Server side)(Base64 encoded)
E459mLf2PeAIMPFy4c3md+BT+AFMtDBsoyP1GjDgbMFc72Ccuvy9Y97vrjYJxilfaOtdaCdo8xQWURnaWjEdHRT3VL/A5bfqEata2L2v8DxnD7hPtSr5tRYVRvsTDm5ByJHR9uh0VwQTz19GOjvG/slHMH0uJJXSOpuMB/brZggMUspY87oGDDcL+z1JuI6elVQtw+weP2kWWQ5gIG/+WbT2MXiKptaq0cqq6sG5oQNni42KCUj2+HADqypqdlVuyk02CgYDe69WQwnb90qILdqiqnyIbRlhoT8Du/DHY+N15ShTUBght6oeqj/cfuUeMtVgIdIP3g+gH/JMdl2sdw==
Please help in the case.

Related

Encrypting java JWEObject with RSA in python

I asked a while ago how to do something similar: Decrypting and encrypting java JWEObject with algorithm RSA-OAEP-256 on python
Now I have a different encryption key and that code is not working for me anymore.
I need to be able to encrypt my data: {"value": "Object Encryption"} with JWE using RSA.
I have this key id: a4d4039e-a8c7-4d06-98c8-2bda90ab169c
and this encryption key:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9JJaeFiDdB+dGvi3jUzKUMU73kG6vvc/P+jwZXRKKpJSwf8PU4SapMyFPFFoHwca6Z8vZogF4ghEJ18JipNyF3BLnfCt1EHuZ15FG1Aywvpi+xw7F0UoJ9DWItBM1SodKXIh1be44/9SiLrpcyROKId349zWMOl3IVVxekLPKWTHsy2Iowp7JsjNEK3t9RdV+PAtUzp1ACyqHD/MDYSmpJuEOR9AbmBayaFIWVP+52q1ir7ea88zocmklDg0SGjiRNXq1tUAljWezpKstKQNz/IZN1kMLQ8SknrlpZL0vjjAnHFlgtLfcwPbESt76surRshfGwwfx8T9AOfXMgELNQIDAQAB
and I should get this:
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiYTRkNDAzOWUtYThjNy00ZDA2LTk4YzgtMmJkYTkwYWIxNjljIn0.2hGqQVSbgZ9-9Hiz8VZizORpWRR2yioHb8vK6R9tQCpxr0jxBGehNL0K36XfJWJC5KxcxDdD9byeI_YTtB_hYTgsuMTHS5p-4aJ4nLk43Ya5yR8p8nn4s11wbkfSj0jbqSFb_1IOCMgX0Xu8lmnVe7Tjc4vACwBoaM6VpudEsLHpyQ9OxNaa1apbRp-BX3DEVM3l7ltHhMIh_DCRWbC4-LbS51L4RqLWxmihqRA97FYX4HX38Vbt3O__2tq5KfSjq78UEOffEFe_CRg8mXZ1CHgyH4YPMNmjS-jAI4m07Coja4zLXgv7ctFaFQePISLaZLgdp3a0a-Sht5cwwZfAhg.mc7_YA9mg3l7VV5B.ZOnYjkiXx1YSxDIILjcHUXluwW8jqsSO5NuIkto.9KtJGJRS9QevrqZPYYlcTQ
That's the java code I'm trying to rewrite in python:
private RSAPublicKey getObjectEncryptionKey()
throws NoSuchAlgorithmException, InvalidKeySpecException {
logger.debug("Getting object encryption key");
if (Objects.isNull(objectEncryptionKey)) {
objectEncryptionKey = getActiveKey(Algorithm.RSA);
}
byte[] encryptionKey = base64Decode(String.valueOf(objectEncryptionKey.getEncryptionKeyValue()).getBytes());
KeyFactory keyFactory = getInstance(Algorithm.RSA.name());
return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(encryptionKey));
}
public String encryptObject(Object object) {
logger.debug("Encrypting object with keyId: {}", getObjectEncryptionKeyId());
JsonWebEncryption encryptedObject = getJWEObject(object);
try {
return encryptedObject.getCompactSerialization();
} catch (JoseException e) {
throw new CryptoException("Could not encrypt object/event", e);
}
}
private JsonWebEncryption getJWEObject(Object object) {
JsonWebEncryption jwe = new JsonWebEncryption();
try {
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
jwe.setKey(getObjectEncryptionKey());
jwe.setKeyIdHeaderValue(getObjectEncryptionKeyId());
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new CryptoException("Could not create JsonWebEncryption", e);
}
}
How is it different from my previous question and what is the correct way to do it in python?
I tried doing something like that:
def grouper(iterable, n, fillvalue=''):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
def decryption_key_to_pem(decryption_key: str) -> bytes:
pem = ['-----BEGIN PRIVATE KEY-----']
for group in grouper(decryption_key, 64):
pem.append(''.join(group))
pem.append('-----END PRIVATE KEY-----')
return str.encode('\n'.join(pem))
jwk.JWK.from_pem(decryption_key_to_pem(key))
but I get this exception:
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=503841036, lib=60, reason=524556, reason_text=b'error:1E08010C:DECODER routines::unsupported'), _OpenSSLErrorWithText(code=109052072, lib=13, reason=168, reason_text=b'error:068000A8:asn1 encoding routines::wrong tag'), _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error'), _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error')])
Also tried something like:
def get_jwe_key(data, encryption_key, encryption_key_id):
jwe = jwcrypto.jwe.JWE()
jwe.plaintext = json.dumps(data).encode('utf-8')
jwe.alg = 'RSA-OAEP-256'
jwe.enc = 'A256GCM'
jwe.recipient = encryption_key
jwe.header = {'kid': encryption_key_id}
return jwe
jwe_key = get_jwe_key(decrypted_data, key, key_id)
jwe_key.serialize()
and I get: jwcrypto.common.InvalidJWEOperation: No available ciphertext
In the JWCrypto documentation you can find examples for the encryption with JWCrypto. You basically only need to insert your values:
from jwcrypto import jwk, jwe
import json
spki_pem = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9JJaeFiDdB+dGvi3jUzK
UMU73kG6vvc/P+jwZXRKKpJSwf8PU4SapMyFPFFoHwca6Z8vZogF4ghEJ18JipNy
F3BLnfCt1EHuZ15FG1Aywvpi+xw7F0UoJ9DWItBM1SodKXIh1be44/9SiLrpcyRO
KId349zWMOl3IVVxekLPKWTHsy2Iowp7JsjNEK3t9RdV+PAtUzp1ACyqHD/MDYSm
pJuEOR9AbmBayaFIWVP+52q1ir7ea88zocmklDg0SGjiRNXq1tUAljWezpKstKQN
z/IZN1kMLQ8SknrlpZL0vjjAnHFlgtLfcwPbESt76surRshfGwwfx8T9AOfXMgEL
NQIDAQAB
-----END PUBLIC KEY-----'''
data = {"value": "Object Encryption"}
public_key = jwk.JWK.from_pem(spki_pem.encode('utf-8'))
payload = json.dumps(data).encode('utf-8')
protected_header = {
"alg": "RSA-OAEP-256",
"enc": "A256GCM",
"kid": "a4d4039e-a8c7-4d06-98c8-2bda90ab169c",
}
jwetoken = jwe.JWE(payload, recipient=public_key, protected=protected_header)
jewcompact = jwetoken.serialize(True)
print(jewcompact)
Possible output:
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiYTRkNDAzOWUtYThjNy00ZDA2LTk4YzgtMmJkYTkwYWIxNjljIn0.DstnMY6WkdCGA1NC0S4JIU3CNVFuUNQSghQyqkh8RpmUyBvnEelvkmWTTf3AApj4jNflnYL_bp8vbeu8PO6CyF1Pi_gUZ1vE1PHHcLD8VZ2eMiIdG08Qq9L7uDlqTIaM6qX0n_uctsm4Y0rflWXrSbr5iwXHxgOQ5XDgLCgg870tObS3RbK2RzrjYRnQs-_hK4R8LRJgCEKeV__fzmU6nx5jA4qXXs_U3y9Uxs3_4OE-xSelPT_yY5xCMs8fAHvaua92mrRCMSu9cp9iAYW8qu3bYdUFjnWqifOQIUB2HljqMH85tCxS02tBuVPs52b8pgNUckqa_v43BvxTbnwuJg.RWtp5j38l8mz_qoJ.2VBsxt1zyk5rAmSvg3k0eMLzIAPo9ttn-7dLB2nP.k4k9ZnCRRA1im2sbvMLlbQ
An encrypted token consists of 5 parts, the header, the encrypted key, the IV/nonce, the actual ciphertext and the tag, each separated by . and Base64url encoded. Since AES generates a different key and IV/nonce for each encryption and RSA encryption is non-deterministic, a different encrypted token is generated for each encryption except for the first part. So you should not expect that the code generates the same encrypted token that you posted.
The generated token can be decrypted using the private key associated with the posted public key and the decryption code of the linked post. This is also the right way for a test.
Edit:
Regarding the first part of your question from the comment: If the header
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiYTRkNDAzOWUtYThjNy00ZDA2LTk4YzgtMmJkYTkwYWIxNjljIn0
of the encrypted token is Base64url encoded, you get:
{"alg":"RSA-OAEP-256","enc":"A256GCM","kid":"a4d4039e-a8c7-4d06-98c8-2bda90ab169c"}
Here A256GCM as enc means that the plaintext is encrypted with AES-256 in GCM mode (symmetric encryption), with a random key being generated for the AES encryption.
RSA-OAEP-256 as alg means that this AES key is encrypted with RSA and with OAEP/SHA256 as padding (asymmetric encryption).
Bear in mind that RSA encryption always uses the public key (of the recipient).
So both cryptography types (symmetric and asymmetric) are involved, which is also called hybrid encryption.
The private RSA key does not come into play at all during encryption, but only during decryption, as you can verify in the linked post. There, the encrypted token is decrypted with the private RSA key (which must be associated with the public key that was used for encryption), meaning more precisely that the symmetric AES key is decrypted with RSA (using the private RSA key), which is then used to decrypt the actual ciphertext.
Regarding the second part: The format and type of the key can be determined with an ASN.1 parser, e.g. https://lapo.it/asn1js/.
The key you posted is an ASN.1/DER encoded public RSA key in X.509/SPKI format that is Base64 encoded. A public RSA key essentially contains modulus and public exponent. A private key also contains the private fields and also uses other formats.

How to use public key to encrypt data and use base64 encode it in python?

I want to implement the following function using python, it uses public key to encrypt the password and then using base64 to encode it. I have searched many answers but I didn't find a solution, I think probably I didn't understand them. Would you please give me some advice?
// # java code
public static String encryptRSA(String password, String publicKey) {
try {
byte[] decoded = Base64.decode(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encode(cipher.doFinal(password.getBytes("UTF-8")));
return outStr;
} catch (Exception e) {
}
return null;
}
I use the following code, but it raises error M2Crypto.RSA.RSAError.
# python code
import base64
import M2Crypto
pub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClnY+3rAf/az9t2bxC80TObpZ2ZCH1xSjPt9QtXl6k6UtD7mQcI2CWSwnDgKJr2m2WnM1kR6X+oOL61lXO0gSuuD8tWOx/knZA2VaSTLdsHBDLOX3e6Fo/O3CtoLVwO5FYFBIFHXMoikPkR8tFIOLWsX0y3slLQQShwSJAHytP4QIDAQAB"
password = 123
def public_encrypt(public_key, password):
rsa_pub = M2Crypto.RSA.load_key_string(public_key.encode('utf-8'))
ctxt_pub = rsa_pub.public_encrypt(password.encode(), M2Crypto.RSA.pkcs1_padding)
ctxt64_pub = base64.b64encode(ctxt_pub).decode()
return ctxt64_pub
res = public_encrypt(pub, password)
print('res:', res)
The full error message is: M2Crypto.RSA.RSAError: no start line, indicating that the key is imported incorrectly.
load_key_string() requires a PEM-encoded private key in PKCS#1 or PKCS#8 format, but no public key. A PEM encoded public key in X.509/SPKI format can be imported with load_pub_key_bio().
From the posted X.509/SPKI key a PEM encoded key can be created by adding a newline after every 64 characters and adding a corresponding header and footer:
import M2Crypto
x509 = '''-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClnY+3rAf/az9t2bxC80TObpZ2
ZCH1xSjPt9QtXl6k6UtD7mQcI2CWSwnDgKJr2m2WnM1kR6X+oOL61lXO0gSuuD8t
WOx/knZA2VaSTLdsHBDLOX3e6Fo/O3CtoLVwO5FYFBIFHXMoikPkR8tFIOLWsX0y
3slLQQShwSJAHytP4QIDAQAB
-----END PUBLIC KEY-----'''
bio = M2Crypto.BIO.MemoryBuffer(x509)
rsa_pub = M2Crypto.RSA.load_pub_key_bio(bio)
Another issue is that there is no encode() defined for an integer, but presumably password is supposed to be a string and this is just a copy/paste error.
With these changes the code works.
Note that a 1024 bits RSA key (like yours) is insecure nowadays, instead the length should be >= 2048 bits.

SwiftyRSA && Python's cryptography for signature verification

I am trying to sign a piece of text using a private key using SwiftyRSA, which I do successfully. Then send the signature to the python server which holds the public key for verification. the But I keep receiving the InvalidSignature exception.
I have tried different hashing algorithms, bit sizes, but still the same InvalidSignature exception. I am sure that the key and signature are related b/c they are generated at the same time!
My issue is not with the libraries themselves--which I think are functioning properly. I think it has to do with a padding discrepancy between the two libraries. Cryptography is using PSS, while I cant find the padding/salt that SwiftyRSA uses.
Key Verification Script
#app.route('/', methods=['POST'])
def verify():
record = json.loads(request.data)
signature = record['sig']
public_key = record['public_key']
hash_local_token = record['hash_local_token']
input_string = record['input_string']
verification_response = auth.verify_signature(signature=signature, pub_key=public_key, input_string=input_string)
print(verification_response)
return jsonify({"Verification": verification_response})
def verify_signature(signature, pub_key, input_string):
# Load the public key
# Url Safe Base64 Decoding
derdata = base64.b64decode(pub_key)
public_key = load_der_public_key(derdata, default_backend())
signature_decoded = base64.urlsafe_b64decode(signature)
# Perform the verification.
try:
public_key.verify(
signature_decoded,
str.encode(input_string),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA256(),
)
return "SUCCESS: Signature Verified!"
except cryptography.exceptions.InvalidSignature as e:
return 'FAILED: Payload and/or signature files failed verification'
Key Generation Script
func moreTesting() {
do {
let keyPair = try SwiftyRSA.generateRSAKeyPair(sizeInBits: 4096)
let privateKey = keyPair.privateKey
let publicKey = keyPair.publicKey
let inputString = "test_string"
let clear = try ClearMessage(string: inputString, using: .utf8)
let signature = try clear.signed(with: privateKey, digestType: .sha256)
let base64Signature = signature.base64String
let parameters: [String: String] = [
"sig": base64Signature,
"input_string": inputString,
"public_key": try publicKey.base64String()
]
AF.request("http://127.0.0.1:5000/", method: .post, parameters: parameters, encoder: JSONParameterEncoder.default).responseJSON { response in
debugPrint(response)
}
}
catch {
print(Error.self)
}
}
It appears that SwiftyRSA's signing APIs use only PKCS1 and not PSS. See: https://github.com/TakeScoop/SwiftyRSA/blob/master/Source/Signature.swift#L20-L27
So to resolve this you'll want to switch your padding from PSS to PKCS1v15 on the Python side.

need to convert following Signnature verification python code to Android?

I create to python3 application that generate the RSA key pairs.
from Crypto.PublicKey import RSA
print("--Private Key Generate--")
key = RSA.generate(2048)
private_key = key.export_key()
file_out = open("key/private.pem", "wb")
file_out.write(private_key)
file_out.close()
print("--Public Key Generate--")
public_key = key.publickey().export_key()
file_out_1 = open("key/receiver.pem", "wb")
file_out_1.write(public_key)
file_out_1.close()
print("key Generated")
I sign some data using python and create a signature. It is also verified using python successfully.
def sign(data):
private_key = RSA.import_key(open('key/private.pem').read())
h = SHA256.new(data)
signature = base64.b64encode(pss.new(private_key).sign(h))
print("signature generate")
verify(data,signature)
return signature
def verify(recive_Data ,signature):
public_key = RSA.import_key(open('key/receiver.pem').read())
h = SHA256.new(recive_Data)
verifier = pss.new(public_key)
try:
verifier.verify(h, base64.b64decode(signature))
print("The signature is authentic")
except (ValueError, TypeError):
print ("The signature is not authentic.")
But actually, my verification implementation in Android(min SDK 23, target SDK 29). So, I need to convert this verification code to Android. I tried using the following code, but not verification success. need some expert help to do it.
public class SecurityHelper {
private static String getKey(InputStream filename) throws IOException {
// Read key from file
String strKeyPEM = "";
BufferedReader br = new BufferedReader(new InputStreamReader(filename));
String line;
while ((line = br.readLine()) != null) {
strKeyPEM += line + "\n";
}
br.close();
// System.out.println(strKeyPEM);
return strKeyPEM;
}
public static PublicKey getPublicKey(InputStream filename) throws IOException, GeneralSecurityException {
String publicKeyPEM = getKey(filename);
return getPublicKeyFromString(publicKeyPEM);
}
public static PublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException {
String publicKeyPEM = key;
publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
System.out.println(publicKeyPEM);
byte[] encoded = Base64.decode(publicKeyPEM ,Base64.CRLF);
// System.out.println(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(encoded));
System.out.println(pubKey);
return pubKey;
}
public static boolean verify(PublicKey publicKey, String message, String signature) throws SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException, InvalidAlgorithmParameterException {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(publicKey);
sign.update(message.getBytes("UTF-8"));
System.out.println(message);
return sign.verify(Base64.decode(signature,Base64.CRLF));
}
}
There are different paddings used, in the Python code PSS and in the Android code Pkcs#1 v1.5, see for the difference RFC 8017. Replace in the Android code SHA256withRSA with SHA256withRSA/PSS.
Update:
Although according to the Android documentation SHA256withRSA/PSS is supported from API level 23+, an InvalidKeyException (No provider supports the provided key) is thrown for API level 23, for API level 24+ it works as specified.
A possible workaround for API level 23 is to use BouncyCastle, which then has to be included as a dependency in the Android project (details depend on the IDE, e.g. here for Android Studio):
implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
Before adding the BC Provider, the pre-installed version must be removed. The schema to be used is SHA256withRSAandMGF1 (see section Signature Algorithms):
Security.removeProvider("BC");
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Signature sign = Signature.getInstance("SHA256withRSAandMGF1");
// Go ahead as for schema SHA256withRSA/PSS...
Note: SpongyCastle would be an alternative possibility. Here the pre-installed BC Provider doesn't have to be removed. The schema is SHA256withRSA/PSS.

how to encrypt a data string with RSA private key in python [duplicate]

I have pkcs8_rsa_private_key file which generate by openssl from a rsa_private_key.pem file.
I need make a signature by the private key in python, make the same signature with below java code.
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
public static String sign(String content, String privateKey) {
String charset = "utf-8";
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(charset));
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
PKCS#8 defines a way to encode and transport secret keys and it is not specific to OpenSSL; PKCS#1 defines a way to use an RSA key (no matter how it was loaded into your application, with PKCS#8 or not) to carry out and verify digital signature on data.
The piece of code you have does three things:
It decodes Base64 into PKCS#8
It decodes PKCS#8 into the actual key in memory (mind you may need to provide a passphrase here)
It performs PKCS#1 v1.5 signature using SHA-1 using said key
It encodes the signature in Base64
The example for PKCS#1 v1.5 signing in the API of PyCrypto does exactly steps #2 and #3.
from Crypto.Signature import PKCS1_v1_5 as pk
from Crypto.Hash import SHA
class Crypt(object):
pkcs8_private_key = RSA.importKey(open('pkcs8_rsa_private_key.pem', 'r').read())
def rsa_sign(cls, des_reqdata):
"""
#:param reqdata: request reqData
"""
h = SHA.new(des_reqdata)
signer = pk.new(cls.pkcs8_private_key)
signature = signer.sign(h)
return base64.b64encode(signature)

Categories

Resources