0

I'm trying to connect to a api in my python app . so the api documentations comes with php and asp sample code but no python

I'm pretty good with php but have no experience with encryption ... I'm trying to re-write python code for the api using php sample .

They use this class for RSA

 https://github.com/AlaFalaki/Pclass/blob/master/libraries/rsa.class.php

(Since its a RSA lib im guessing python RSA lib would take care of this part ) :

static function rsa_sign($message, $private_key, $modulus, $keylength) {
  $padded = RSA::add_PKCS1_padding($message, false, $keylength / 8);
  $number = RSA::binary_to_number($padded);
  $signed = RSA::pow_mod($number, $private_key, $modulus);
  $result = RSA::number_to_binary($signed, $keylength / 8);
  return $result;
 }

Here is the problem php sign function takes 4 arguments uses some internal functions ... But python rsa has 3 and one of them is just the hash method !

rsa.sign(message, priv_key, hash)
Parameters: 
  message – the message to sign. Can be an 8-bit string or a file-like object. If message has a read() method, it is assumed to be a file-like object.
     priv_key – the rsa.PrivateKey to sign with
     hash – the hash method used on the message. Use ‘MD5’, ‘SHA-1’, ‘SHA-256’, ‘SHA-384’ or ‘SHA-512’.

i've tried little experiment to see if i get same output

so i've singed a simple text string in php

echo base64_encode(RSA::rsa_sign(sha1("test"),$private_key,$modulus,$key_length));

i got

something like

dKt+4CocMNdIrtYCUr8aZykR8CpfmYUEEVONMuAPlM5mR70AoyzMhGjcEGB9fKLVC4rr5xt66w2ZmHqWO+p834rJmo9Fj57udRSY5wFs0VokMF2S2SMFn5WTYYmMBuWciRzZybWnfXcSIyp9Ibi28cdwl5hXJOMpXEJrNQLFy2s=

next i extracted private_key , public_key , modulus from a xml file that they gave me with api containing my keys ( using the same RSA class ) like

$xmlObj = simplexml_load_string($xmlRsakey);

        $this->modulus = RSA::binary_to_number(base64_decode($xmlObj->Modulus));
        $this->public_key = RSA::binary_to_number(base64_decode($xmlObj->Exponent));
        $this->private_key = RSA::binary_to_number(base64_decode($xmlObj->D));
        $this->key_length = strlen(base64_decode($xmlObj->Modulus))*8;

i made a python dictionary with them

def keys():
        obj = {
            'modulus' : "14417185111734127374105962730273......." ,
            'public_key' : "61111" ,
            'private_key' : "3739752306322843055980611965983321761993....." ,
            'key_length' : 1024 ,
        }
        return obj

and i've tried to sign a string in python

def sign(request):
    api  = keys()
    message = 'test'
    crypto = rsa.sign(message.encode('utf-8'), api['private_key'] , 'SHA-1')
    b64 = base64.b64encode(crypto)
    return HttpResponse(b64)

but i get :

'str' object has no attribute 'n'

and that was my failed experiment

As i said i dont have any experience with encryption or rsa .... i want some advice from someone who worked with this stuff .

Should i give up and use php to encrypt/decrypt ?

2
  • 1
    My gut says that PHP and Python have implemented things ... differently. I can't say how. My gut also says (perhaps from a biased point-of-view) that the Python lib is statistically more likely to hove to the standards than PHP. If this is a one-time conversion, I suggest whatever is expedient, move your data over, and be done with it. Life is too short, etc. Commented Jun 17, 2016 at 2:17
  • @PeterRowell well it's tow-time conversion connection and verifying data after user came back ... im going to use php for now but i'll keep eye on this question ... i think right now problem is my private_key , php uses a string for pk but python needs something complex like dic , that's why i get the error when i pass my php private key to python rsa function Commented Jun 17, 2016 at 10:58

1 Answer 1

1

They use this class for RSA

https://github.com/AlaFalaki/Pclass/blob/master/libraries/rsa.class.php

My advice: Run away screaming.

RSA is a mine field of security issues. There are a lot of things that you can screw up. So when someone implements the primitives in PHP using the BC extension, that's the security equivalent of standing naked in front of a firing squad and expecting to have no holes.

Recommendation: Use Libsodium Instead

There are both PHP and Python bindings available for libsodium.

If RSA is Unavoidable...

If you really want RSA and not modern cryptography, check out phpseclib.

<?php
use 
$rsa = new RSA();

// HIGHLY RECOMMENDED FOR SECURITY:
$rsa->setEncryptionMode(RSA::ENCRYPTION_OAEP);
$rsa->setMGFHash('sha256');

$rsa->loadKey($yourPEMencodedRSAPublicKey);
$ciphertext = $rsa->encrypt($plaintext);

If you're going to encrypt with RSA, you must follow these cryptography rules. If your library doesn't let you follow these rules, it's time to switch to libsodium.

Also note that encrypting large messages with RSA is both slow and dangerous: There's usually nothing preventing messages from being reordered, which can be really bad.

The solution here is: Use symmetric-key authenticated encryption and use RSA to encrypt the public key. That's what EasyRSA does, although I'm not aware of any Python equivalents, so I can't recommend that as a solution.

Of course, if you use libsodium's crypto_box API you don't have to worry about that!

Sign up to request clarification or add additional context in comments.

2 Comments

thanx , im using their api so they decide what kind of encryption i should use so thats that ... thanx for a great answer i got some reading to do and i'll get back to you
I think phpseclib does OAEP by default, which would make the $rsa->setEncryptionMode(RSA::ENCRYPTION_OAEP); line redundant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.