How to make Botan RSA signature verification match that of PyCrypto
Question: I'm developing a key generator that generates RSA signatures that are to be
downloaded to the clients computer.

In the clients computer i would like to use a RSA signature and a public key
to validate the string. What i would like to know, if you can help, is what is
the algorithm that i should use to get the signature validated or what is
wrong with my code.

[edit updated the code with the suggestion, but still no success.]

The Python code:

    
    
    from Crypto.Signature import PKCS1_PSS
    from Crypto.Hash import SHA
    from Crypto.PublicKey import RSA
    from Crypto import Random
    
    key_priv = RSA.generate(1024)#, random_generator)
    #key_priv = RSA.importKey(open('key.priv.pem.rsa').read())
    
    key_pub  = key_priv.publickey()
    n, e = key_pub.n, key_pub.e
    
    p,q,d,u = key_priv.p, key_priv.q, key_priv.d, key_priv.u
    
    print "char n[] = \"",n,"\";"
    print "char e[] = \"",e,"\";"
    
    #print "key_pub.exportKey(): ",key_pub.exportKey()
    
    mac = '192.168.0.106'
    plugin = 'Bluetooth'
    text = plugin + mac
    
    hash = SHA.new()
    hash.update(text)
    
    #signature = key_priv.sign(hash, None, 'PKCS1')[0]
    #print "signature: ", signature
    
    #random_generator = Random.new().read
    #signature = key_priv.sign(hash, '')
    
    signer    = PKCS1_PSS.new(key_priv)
    
    # signature = signer.sign(hash)
    signature = open('plugin_example.signature').read()
    
    print "type(signature)", type(signature) #str
    print "signature: ", signature
    
    verifier = PKCS1_PSS.new(key_pub)
    if verifier.verify(hash, signature):
        print "The signature is authentic."
    else:
        print "The signature is not authentic."
    
    fd = open("plugin_example.signature", "w")
    fd.write(signature)
    fd.close()
    
    fd = open("key.pub.pem.rsa", "w")
    fd.write(key_pub.exportKey())
    fd.close()
    
    fd = open("key.priv.pem.rsa", "w")
    fd.write(key_priv.exportKey())
    fd.close()
    

And the C++ Code:

    
    
    #include <string.h>
    #include <assert.h>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <memory>
    #include <vector>
    
    #include <botan/botan.h>
    #include <botan/look_pk.h>
    #include <botan/rsa.h>
    
    #include <QtCore>
    #include "lib/debug.hpp"
    #include <QDebug>
    
    #define Q(AAA) qDebug() << #AAA <<" " << AAA << endl;
    #define P(X) std::cout << #X <<" = " << X << " "<< std::endl;
    
    using namespace Botan;
    
    static BigInt to_bigint(const std::string& h)
    {
        return BigInt::decode((const byte*)h.data(),
                              h.length(), BigInt::Hexadecimal);
    }
    
    
    int main(int argc, char ** argv) {
    
        Botan::LibraryInitializer init;
    
        QByteArray mac = "192.168.0.106";
        QByteArray plugin = "Bluetooth";
        QByteArray mac_and_plugin = plugin+mac;
    
        QByteArray mac_and_plugin_hex = QCryptographicHash::hash ( mac_and_plugin, QCryptographicHash::Sha1 ).toHex();
    
        QByteArray qByteArray_sig;
        QFile file ( argv[1] );
        file.open ( QIODevice::ReadOnly );
        if ( file.isReadable() )
        {
            qByteArray_sig = file.readAll();
        }
        file.close();
    
        QByteArray qByteArray_sig_hex = qByteArray_sig.toHex();
    
        char n[] = "137758869720100695031597743484335597584728606037599895664824678915370363634933922524373276431650126408515526550739072301333537631796375930381713667037665579467940926539847824669399430790335904629465572107797677521774814742987023253982675971904413266030976887012380999213491205226382726115118193377641942499979";
        char e[] = "65537";
    
        BigInt big_n = to_bigint(n);// mod
        BigInt big_e = to_bigint(e);// exp
        RSA_PublicKey pub_key(big_n,big_e);
    
        PK_Verifier* verifier = 0;
    
        QStringList l;
        l.push_back("EMSA1(SHA-1)");
        l.push_back("EMSA3(SHA-1)");
        l.push_back("EMSA4(SHA-1)");
        l.push_back("EMSA1(SHA-256)");
        l.push_back("EMSA3(SHA-256)");
        l.push_back("EMSA4(SHA-256)");
        l.push_back("EMSA3(MD5)");
    
        P(qByteArray_sig.length());
    
        for (int i = 0 ; i < l.size(); i++) {
            if (verifier)
                delete verifier;
            verifier = get_pk_verifier(pub_key, l[i].toStdString() );
    
            bool is_valid = verifier->verify_message(
                                mac_and_plugin_hex.data(),mac_and_plugin_hex.length(),
                                qByteArray_sig_hex.data(), qByteArray_sig_hex.length()
                            );
            P(is_valid);
    
            is_valid = verifier->verify_message(
                          mac_and_plugin_hex.data(),mac_and_plugin_hex.length(),
                          qByteArray_sig.data(), qByteArray_sig.length()
                      );
            P(is_valid);
    
            is_valid = verifier->verify_message(
                          mac_and_plugin.data(),mac_and_plugin.length(),
                          qByteArray_sig.data(), qByteArray_sig.length()
                      );
            P(is_valid);
    
        }
    
        Q(qByteArray_sig);
        Q(qByteArray_sig_hex);;
    }
    


Answer: In the piece of Python code, you are creating an RSA signature that does not
follow any real protocol or standard. In other words, it's _raw_ and in most
cases it is not secure.

Instead, you should use something like PSS (use the pycrypto module [PKCS1_PSS
here](https://www.dlitz.net/software/pycrypto/api/current/Crypto.Signature.PKCS1_PSS-
module.html)). In the Botan code, that can by verified with the EMSA4
encoding.

Alternatively you could use [PKCS#1
v1.5](https://www.dlitz.net/software/pycrypto/api/current/Crypto.Signature.PKCS1_v1_5-module.html).
In Botan, that is EMSA3.

In either case, the hash algorithm must be the same at both sides.

