web-dev-qa-db-fra.com

C++ traitant de très grands entiers

J'utilise l'algorithme RSA pour le cryptage/décryptage. Pour décrypter les fichiers, vous devez gérer de très grandes valeurs. Plus spécifiquement, des choses comme 

P = C^d % n
  = 62^65 % 133

Maintenant, c’est vraiment les seuls calculs que je puisse faire. J'ai essayé d'utiliser la bibliothèque BigInteger de Matt McCutchen, mais je reçois beaucoup d'erreurs de compilateur lors de la liaison, telles que:

encryption.o(.text+0x187):encryption.cpp: undefined reference to `BigInteger::BigInteger(int)'

encryption.o(.text+0x302):encryption.cpp: undefined reference to `operator<<(std::ostream&, BigInteger const&)'

encryption.o(.text$_ZNK10BigIntegermlERKS_[BigInteger::operator*(BigInteger const&) const]+0x63):encryption.cpp: undefined reference to `BigInteger::multiply(BigInteger const&, BigInteger const&)'

Je me demandais donc quelle serait la meilleure façon de gérer les très grands nombres entiers issus de l’algorithme RSA.

J'ai entendu dire qu'une possibilité serait de déclarer vos variables comme un double long, alors ...

long long decryptedCharacter;

mais je ne sais pas exactement quelle taille d'un entier pouvant stocker.


Par exemple, j’essaie de compiler et d’exécuter le programme suivant à l’aide de dev C++:

#include iostream

#include "bigint\BigIntegerLibrary.hh"

using namespace std;

int main()
{
    BigInteger a = 65536;
    cout << (a * a * a * a * a * a * a * a);
    return 0;
}

alors je reçois ces erreurs.

Derek, je pensais qu'en incluant le fichier BigIntegerLibrary.hh, le compilateur passerait par là et compilerait tous les fichiers nécessaires qu'il utiliserait.

Comment dois-je essayer de compiler le programme ci-dessus afin de résoudre les erreurs de liaison?

20
Tomek

Méta-réponse:

Si vous utilisez une bibliothèque pour l'arithmétique bigint, demandez-vous pourquoi vous n'utilisez pas une bibliothèque pour toute la mise en œuvre de RSA.

Par exemple, http://www.gnu.org/software/gnu-crypto/ contient une implémentation RSA. Il a la même licence que GMP.

Cependant, ils n'ont pas la même licence que http://mattmccutchen.net/bigint/ , qui me semble avoir été placée dans le domaine public aux États-Unis.

23
Steve Jessop

Tomek, il semble que vous ne liez pas correctement le code BigInteger. Je pense que vous devriez résoudre ce problème plutôt que de chercher une nouvelle bibliothèque. J'ai jeté un coup d'œil à la source, et BigInteger::BigInteger(int) est très clairement défini. Un bref coup d’œil indique que les autres le sont aussi.

Les erreurs de lien que vous obtenez impliquent que vous négligez soit de compiler la source BigInteger, soit d'inclure les fichiers d'objet résultants lorsque vous créez un lien. Veuillez noter que la source BigInteger utilise l'extension "cc" plutôt que "cpp", assurez-vous donc que vous compilez également ces fichiers.

12
Derek Park

Je suggérerais d'utiliser gmp , il peut gérer des ints arbitrairement longs et possède des liaisons C++ décentes.

autant que je sache sur le matériel/logiciel actuel très long sont 64 bits, unsigned peut donc traiter des nombres allant jusqu'à (2 ** 64) -1 == 18446744073709551615, ce qui est un peu plus petit que les nombres que vous auriez à traiter avec RSA.

12
TFKyle

Pour voir la taille d'un long long essayez ceci:

#include <stdio.h>

int main(void) {
    printf("%d\n", sizeof(long long));

    return 0;
}

Sur ma machine, il renvoie 8, ce qui signifie 8 octets pouvant stocker 2 ^ 64 valeurs.

4
Jeremy Ruten

La sécurisation de la mise en œuvre de RSA ne se limite pas aux grands nombres. Une implémentation RSA simple a tendance à laisser échapper des informations privées par les canaux secondaires, en particulier la synchronisation (en termes simples: le temps de calcul dépend des données traitées, ce qui permet à un attaquant de récupérer une partie, voire la totalité, des bits de la clé privée). De bonnes implémentations RSA implémentent des contremesures.

En outre, au-delà de l'exponentiation modulaire, il existe toute l'activité de rembourrage, qui n'est pas conceptuellement difficile, mais qui, comme toutes les E/S et le code d'analyse, peut faire place à des bogues subtils. Le code le plus facile à écrire est le code qui a déjà été écrit par quelqu'un d'autre.

Un autre point est qu’une fois que votre code RSA est opérationnel, vous pouvez commencer à envisager des extensions et d’autres situations, par exemple. "que se passe-t-il si la clé privée que je veux utiliser ne se trouve pas dans RAM mais dans une carte à puce?". Certaines implémentations RSA existantes sont en réalité des API capables de gérer cela. Dans le monde Microsoft, vous souhaitez rechercher CryptoAPI , intégré à Windows. Vous voudrez peut-être aussi regarder NSS , qui correspond à ce que le navigateur Firefox utilise pour SSL.

Pour résumer: vous pouvez / construire une implémentation conforme à RSA à partir de grands entiers, mais il est plus difficile de faire correctement que ce qui semble en général, mon conseil est donc d'utiliser une implémentation RSA existante.

3
Thomas Pornin

Voici mon approche, elle combine une exponentiation rapide en utilisant une exponentiation au carré + modulaire qui réduit l'espace requis.

long long mod_exp (long long n, long long e, long long mod)
{
  if(e == 1)
  {
       return (n % mod);
  }
  else
  {
      if((e % 2) == 1)
      {
          long long temp = mod_exp(n, (e-1)/2, mod);
          return ((n * temp * temp) % mod);
      }
      else
      {
          long long temp = mod_exp(n, e/2, mod);
          return ((temp*temp) % mod); 
      }
  }
}
3
Vlad

Si vous n'implémentez pas RSA en tant que tâche scolaire, je vous suggère de consulter la bibliothèque crypto ++ http://www.cryptopp.com

C’est tellement facile d’implémenter mal la crypto.

3
tfinniga

Pour RSA, vous avez besoin d’une bibliothèque bignum. Les chiffres sont beaucoup trop gros pour tenir dans un long 64 bits. Un de mes collègues à l'université a eu la tâche de mettre en œuvre RSA, y compris de créer sa propre bibliothèque Bignum.

En l'occurrence, Python possède une bibliothèque bignum. L'écriture de gestionnaires de bignum est assez petite pour s'intégrer à une mission en informatique, mais elle a encore suffisamment de pièges pour en faire une tâche non triviale. Sa solution consistait à utiliser la bibliothèque Python pour générer des données de test afin de valider sa bibliothèque bignum.

Vous devriez pouvoir obtenir d’autres bibliothèques bignum.

Sinon, essayez d'implémenter un prototype en Python et voyez si c'est assez rapide.

J'essayerais la bibliothèque GMP - elle est robuste, bien testée et couramment utilisée pour ce type de code.

2
Greg Hewgill

Openssl possède également un type Bignum que vous pouvez utiliser. Je l'ai utilisé et ça marche bien. Facile à envelopper dans un langage oo comme C++ ou Objective-C, si vous voulez.

https://www.openssl.org/docs/crypto/bn.html

De plus, si vous ne le saviez pas, pour trouver la réponse à l'équation de cette forme x ^ y% z, recherchez un algorithme appelé exponentiation modulaire. La plupart des bibliothèques crypto ou bignum auront une fonction spécifique pour ce calcul.

2
robottobor

Un long int est typiquement de 64 bits, ce qui ne serait probablement pas suffisant pour gérer un entier aussi grand. Vous aurez probablement besoin d'une bibliothèque bigint quelconque.

Voir aussi cette question sur Stack Overflow

1
Adam Pierce

Consultez la documentation de votre compilateur. Certains compilateurs ont des types définis tels que __int64 qui vous donnent leur taille. Peut-être que vous en avez certains disponibles.

1
Scott Langham

Notons que __int64 et long long sont des extensions non standard. Aucun des deux n'est garanti d'être pris en charge par tous les compilateurs C++. C++ est basé sur C89 (il est sorti en 98, donc il ne pourrait pas être basé sur C99)

(C supporte "depuis longtemps" depuis C99)

En passant, je ne pense pas que les entiers 64 bits résolvent ce problème.

1
David Ameller

J'ai eu beaucoup de succès en utilisant la librairie LibTomCrypt pour mes besoins en cryptographie. C'est rapide, maigre et portable. Il peut faire votre RSA pour vous, ou simplement gérer le calcul si vous voulez.

1
adum

Le fait que vous ayez un problème à utiliser une bibliothèque biginteger ne signifie pas que c'est une mauvaise approche. 

Utiliser longtemps est définitivement une mauvaise approche. 

Comme d'autres l'ont déjà dit, utiliser une bibliothèque biginteger est probablement une bonne approche, mais vous devez publier plus de détails sur le mode d'utilisation de la bibliothèque mentionnée pour que nous puissions vous aider à résoudre ces erreurs.

0
Maciej Hehl

J'ai utilisé GMP lorsque j'ai écrit l'implémentation RSA.

0
Vaibhav Bajpai