Maison > php教程 > PHP开发 > le corps du texte

Cryptage et décryptage Golang RSA (avec php)

高洛峰
Libérer: 2016-12-30 09:08:02
original
1820 Les gens l'ont consulté

Un bref historique de l'algorithme de chiffrement RSA

RSA a été inventé en 1977 par Ron Rivest, Adi Shamir et Leonard Adleman ) ont été proposés ensemble. Tous trois travaillaient au MIT à l’époque. RSA est composé des premières lettres de leurs noms de famille épelées ensemble.

Principe de l'algorithme de cryptage RSA

Les amis qui ont étudié les algorithmes savent que les algorithmes des ordinateurs sont en fait des opérations mathématiques. Par conséquent, avant d’expliquer l’algorithme de cryptage RSA, il est nécessaire de comprendre certaines connaissances mathématiques nécessaires. Commençons par les connaissances mathématiques.

Connaissances mathématiques nécessaires

Dans l'algorithme de cryptage RSA, seules quelques connaissances mathématiques simples telles que les nombres premiers, les nombres premiers entre eux, les opérations exponentielles et les opérations modulaires sont utilisées. Par conséquent, nous devons également comprendre ces concepts.

Nombre premier

Un nombre premier, également appelé nombre premier, fait référence à un nombre naturel supérieur à 1 qui n'est pas divisible par d'autres nombres naturels sauf 1 et l'entier lui-même. Nous avons tous appris ce concept au collège et même à l’école primaire, je ne vais donc pas trop l’expliquer ici.

Nombres co-premiers

L'explication sur l'Encyclopédie Baidu est la suivante : Deux nombres avec un facteur commun de seulement 1 sont appelés nombres co-premiers. ;L'explication sur Wikipédia est : co-prime, également connu sous le nom de co-prime. Si le plus grand commun diviseur de N entiers est 1, alors ces N entiers sont dits relativement premiers.

Les méthodes courantes courantes pour juger les nombres premiers entre eux sont les suivantes :

1. Deux nombres premiers différents doivent être des nombres premiers entre eux. Par exemple, 2 et 7, 13 et 19.

2. Si un nombre premier et l'autre n'en sont pas un multiple, ces deux nombres sont premiers entre eux. Par exemple, 3 et 10, 5 et 26.

3. Deux nombres naturels adjacents sont premiers entre eux. Comme 15 et 16.

4. Deux nombres impairs adjacents sont premiers entre eux. Comme 49 et 51.

5. Deux nombres dont le plus grand nombre est premier sont premiers entre eux. Comme 97 et 88.

6. Les nombres décimaux sont des nombres premiers, et deux nombres qui ne sont pas des multiples d'un nombre décimal sont premiers entre eux. Par exemple 7 et 16.

7, 2 et tout nombre impair sont des nombres premiers entre eux. Par exemple 2 et 87.

8. 1 n'est ni un nombre premier ni un nombre composé Il est premier avec n'importe quel nombre naturel. Tels que 1 et 9908.

9. Division euclidienne.

Opération exponentielle

L'opération exponentielle est également appelée calcul d'exponentiation, et le résultat du calcul est appelé puissance. nm fait référence à la multiplication de n par lui-même m fois. Le résultat du traitement de nm comme une puissance est appelé « n élevé à la puissance m » ou « n élevé à la puissance m ». Parmi eux, n est appelé la « base » et m est appelé « l’exposant ».

Opération Modulo

L'opération Modulo est l'opération reste. "Module" est la translittération de "Mod". Un concept étroitement lié à l'arithmétique modulaire est la « congruence ». Mathématiquement, lorsque deux entiers sont divisés par le même entier positif et obtiennent le même reste, alors les deux entiers sont congrus.

Deux entiers a, b, si les restes obtenus en les divisant par un entier positif m sont égaux, alors a et b sont dits congrus modulo m, notés : a ≡ b (mod m) ; lire comme : a est congru à b modulo m, ou a et b sont congrus modulo m. Par exemple : 26 ≡ 14 (mod 12).

Algorithme de cryptage RSA

Génération d'une clé publique et d'une clé secrète

Supposons qu'Alice veuille recevoir un message privé de Bob via un support peu fiable. Elle peut générer une clé publique et une clé privée de la manière suivante :

1. Choisir au hasard deux grands nombres premiers p et q, p n'est pas égal à q, et calculer N=pq.

2. D'après la fonction Euler, trouvez r = (p-1)(q-1)

3. Choisissez un entier e inférieur à r , et trouvez Obtenez l'élément inverse modulaire de e par rapport au modulo r, et nommez-le d. (L'élément inverse modulaire existe si et seulement si e et r sont premiers entre eux)

4. Détruisez les enregistrements de p et q.
(N,e) est la clé publique, (N,d) est la clé privée. Alice transmet sa clé publique (N,e) à Bob et cache sa clé privée (N,d).

Message crypté

Supposons que Bob veuille envoyer un message m à Alice, et qu'il connaisse le N et le e générés par Alice. Il utilise le format initialement convenu avec Alice pour convertir m en un entier n inférieur à N. Par exemple, il peut convertir chaque mot en code Unicode du mot, puis relier ces nombres entre eux pour former un nombre. Si son message est très long, il peut diviser le message en plusieurs paragraphes puis convertir chaque paragraphe en n. A l'aide de la formule suivante, il peut chiffrer n en c :

 ne ≡ c (mod N)

Calculer c n'est pas compliqué. Une fois que Bob a compris c, il peut le transmettre à Alice.

Déchiffrer le message

Après qu'Alice ait reçu le message c de Bob, elle peut utiliser sa clé d pour le décoder. Elle peut utiliser la formule suivante pour convertir c en n :

cd ≡ n (mod N)

Après avoir obtenu n, elle peut restaurer les informations d'origine m.

Le principe du décodage est :

 cd ≡ n e·d(mod N)

et ed ≡ 1 (mod p-1) et ed ≡ 1 (mod q - 1). Cela peut être prouvé par le petit théorème de Fermat (car p et q sont des nombres premiers)

 n e·d ≡ n (mod p)  Et n e·d ≡ n (mod q)

Cela montre (parce que p et q sont des nombres premiers différents, donc p et q sont relativement premiers)

 n e·d ≡ n (mod pq)

Message signé

 RSA peut aussi être utilisé pour une signature de message. Si A souhaite transmettre un message signé à B, alors il peut calculer une valeur de hachage (Message digest) pour son message, puis utiliser sa clé (clé privée) pour chiffrer la valeur de hachage et ajouter cette « signature » à la fin de le message. Ce message ne peut être déchiffré qu'à l'aide de sa clé publique. Une fois que B a obtenu le message, il peut utiliser la clé publique de A pour déchiffrer la valeur de hachage, puis comparer ces données avec sa propre valeur de hachage calculée pour le message. Si les deux correspondent, alors il peut savoir que l'expéditeur détient la clé de A et que le message n'a pas été falsifié pendant le chemin de propagation.

Chiffrement et décryptage Golang RSA

En PHP, de nombreuses fonctions sont souvent résolues par une seule fonction mais en Go, ce n'est pas le cas. Cet article apprendra l'API liée à RSA de Go via le cryptage PHP, le cryptage Go, le déchiffrement PHP.

Cet article traite du cryptage et du déchiffrement Go RSA. Toutes les opérations sont réalisées sous Linux.

1. Présentation

Il s'agit d'un algorithme de chiffrement asymétrique qui utilise généralement le chiffrement à clé publique et le déchiffrement à clé privée.

Pendant le processus de cryptage et de décryptage, openssl est utilisé pour générer la clé. Effectuez les opérations suivantes :

1) Créer une clé privée :

openssl genrsa -out private.pem 1024 //密钥长度,1024觉得不够安全的话可以用2048,但是代价也相应增大
Copier après la connexion

2) Créer une clé publique :

openssl rsa -in private.pem -pubout -out public.pem
这样便生产了密钥。
Copier après la connexion

Généralement, chaque langage fournira également une API pour générer des clés. Dans Go, consultez le package encoding/pem et le package crypto/x509.

Le cryptage et le décryptage impliquent de nombreuses normes. Je recommande personnellement de les apprendre temporairement en cas de besoin.

2. Allez au cryptage et au décryptage RSA

1. Pour le cryptage et le décryptage rsa, vous vérifierez certainement le package crypto/ras

Package rsa implements RSA encryption as specified in PKCS#1.
Copier après la connexion

Voici la description du package : Implémente la technologie de cryptage RSA, basée sur la spécification PKCS#1.

Pour ce qu'est PKCS#1, vous pouvez vérifier les informations pertinentes. PKCS (Public Key Cryptozoology Standard) et n°1 est la norme RSA. Vous pouvez consulter : Introduction à la série PKCS

À partir des noms des fonctions de ce package, vous pouvez voir qu'il existe deux paires de fonctions de cryptage et de déchiffrement.

EncryptOAEP和DecryptOAEP
EncryptPKCS1v15和DecryptPKCS1v15
Copier après la connexion

C'est ce qu'on appelle un schéma de cryptage. Vous pouvez afficher les détails de la norme d'algorithme RSA PKCS #1

lorsque vous interagissez avec d'autres. langues, il est nécessaire de décider quelle solution utiliser.

Les deux types PublicKey et PrivateKey représentent respectivement les clés publiques et privées. Concernant la façon de définir les membres de ces deux types, cela implique l'algorithme de cryptage RSA. Dans cet article, des exemples de ces deux types sont analysés. l'article La clé générée au début est obtenue.

2. Analyser la clé pour obtenir des instances de PublicKey et PrivateKey

Ce processus m'a également pris beaucoup de temps (principalement, je ne suis pas familier avec diverses choses de cryptage) : Comment analyser la clé fichier généré par openssl dans des instances de clé publique et de clé privée ?

Dans le package encoding/pem, j'ai vu les mots --BEGIN Type ---. Ceci est similaire au formulaire de clé généré par openssl, alors essayez-le.

Dans ce package, un bloc représente la structure de l'encodage PEM. Pour PEM, veuillez vérifier les informations pertinentes. Nous voulons analyser la clé, bien sûr en utilisant la méthode Decode :

func Decode(data []byte) (p *Block, rest []byte)
Copier après la connexion

De cette façon, nous obtenons une instance Block (pointeur).

Analyse pour voir crypto/x509. Pourquoi x509 ? Cela implique encore une fois un tas de concepts. Indépendamment de cela, je l’ai également découvert en examinant les sous-packages des packages d’encodage et de cryptographie.

Dans le package x509, il y a une fonction :

func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
Copier après la connexion

D'après la description de la fonction : ParsePKIXPublicKey analyse une clé publique codée en DER. les valeurs se trouvent généralement dans les blocs PEM avec « BEGIN PUBLIC KEY ». On peut voir qu'il s'agit de l'analyse de PublicKey. De plus, en ce qui concerne PEM ici, l'encodage/pem ci-dessus peut être correct.

Il existe plusieurs méthodes pour analyser les clés privées. D'après l'introduction ci-dessus, nous savons que RSA est PKCS#1, et il n'y a qu'une seule méthode :

func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
Copier après la connexion

<🎜. > Ce qui est renvoyé est rsa.PrivateKey.

3. Décryptage et implémentation du décryptage


Grâce à l'introduction ci-dessus, il n'est pas difficile d'implémenter le décryptage et le décryptage RSA dans Go. Le code est le suivant :

// Chiffrement

func RsaEncrypt(origData []byte) ([]byte, error) {
  block, _ := pem.Decode(publicKey)
  if block == nil {
    return nil, errors.New("public key error")
  }
  pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  if err != nil {
    return nil, err
  }
  pub := pubInterface.(*rsa.PublicKey)
  return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
Copier après la connexion

// Décryptage

func RsaDecrypt(ciphertext []byte) ([]byte, error) {
  block, _ := pem.Decode(privateKey)
  if block == nil {
    return nil, errors.New("private key error!")
  }
  priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  if err != nil {
    return nil, err
  }
  return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
Copier après la connexion

其中,publicKey和privateKey是openssl生成的密钥,我生成的如下:

// 公钥和私钥可以从文件中读取

var privateKey = []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O
-----END RSA PRIVATE KEY-----
`)
  
var publicKey = []byte(`
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END PUBLIC KEY-----
`)
Copier après la connexion

4、使用例子

package main
  
import (
  "fmt"
)
 
func main() {
  data, err := RsaEncrypt([]byte("git@github.com/mrkt"))
  if err != nil {
    panic(err)
  }
  origData, err := RsaDecrypt(data)
  if err != nil {
    panic(err)
  }
  fmt.Println(string(origData))
}
Copier après la connexion

该例子是加密完git@github.com/mrkt后立马解密

三、跨语言加解密

语言内部正常,还得看看和其他语言是否一致,即:其他语言加密,Go语言得正确解密;Go语言加密,其他语言正确解密

1、PHP RSA加解密

这里,我选择PHP,使用的是openssl扩展。PHP中加解密很简单,如下两个方法(这里只考虑用公钥加密,私钥解密):

bool openssl_public_encrypt ( string $data , string &$crypted , mixed
$key [, int $padding = OPENSSL_PKCS1_PADDING ] ) bool
openssl_private_decrypt ( string $data , string &$decrypted , mixed
$key [, int $padding = OPENSSL_PKCS1_PADDING ] )
Copier après la connexion

最后一个参数是加密方案(补齐方式)。由于Go中使用的是PKCS1而不是OAEP,所以,使用默认值即可。

PHP代码如下:

$privateKey = &#39;-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y
7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7
Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB
AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM
ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1
XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB
/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40
IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG
4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9
DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8
9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw
DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO
AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O
-----END RSA PRIVATE KEY-----&#39;; $publicKey = &#39;-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv
ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd
wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL
AUeJ6PeW+DAkmJWF6QIDAQAB
-----END PUBLIC KEY-----&#39;;
function rsaEncrypt($data)
{
  global $publicKey;
  openssl_public_encrypt($data, $crypted, $publicKey);
  return $crypted;
 
}
function rsaDecrypt($data)
{
  global $privateKey;
  openssl_private_decrypt($data, $decrypted, $privateKey);
  return $decrypted;
}
 
function main()
{
 
  $crypted = rsaEncrypt("git@github.com/mrk");
  $decrypted = rsaDecrypt($crypted);
  echo "encrypt and decrypt:" . $decrypted;
 
}
Copier après la connexion

   


main();

这里也是用PHP加解密git@github.com/mrkt

2、Go和PHP一起工作

这里要注意的一点是,由于加密后是字节流,直接输出查看会乱码,因此,为了便于语言直接加解密,这里将加密之后的数据进行base64编码。

3、使用

示例中,php和Go版本都支持-d参数传入加密好的字符串,将其解密;不传时,会输出加密好并base64编码的串,可用于其他语言解密。

总结

以上就是用Go语言实现了RSA的加密解密的全部内容,文章很深入的讲解了RSA的加密解密过程,对学习相关知识的朋友很有帮助。如果有疑问欢迎留言讨论。

更多Golang加密解密之RSA(附带php)相关文章请关注PHP中文网!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Recommandations populaires
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!