PyArmor ~ Un moyen facile de chiffrer et de fournir du code source Python ~

introduction

Lors de l'élaboration de contrats, je pense qu'il y a des situations où vous devez livrer les livrables au client. Dans un tel cas, par exemple, si la fonction peut être fournie en SaaS, le côté client appuiera sur l'API et utilisera la fonction, il ne sera donc bien sûr pas possible de saisir le code source de ce côté. Cependant, je pense que dans de nombreuses situations, ce n'est pas réaliste. Il existe une bibliothèque appelée PyArmor qui est utile dans de tels cas. PyArmor est une bibliothèque qui crypte le code source et, en théorie, le code source ne peut pas être restauré. C'est une bibliothèque très pratique lorsque vous souhaitez livrer rapidement le code source. Outre le simple chiffrement, il est également possible de chiffrer après l'octroi de diverses licences (période d'utilisation, dispositif d'exécution, etc.). Concernant PyArmor, d'autres articles sortiront si vous google, mais comme les spécifications ont légèrement changé, j'ai essayé de le résumer sous forme d'article cette fois en incluant la signification du mémo. Pour savoir comment utiliser PyArmor, reportez-vous au document officiel ci-dessous.

Document officiel PyArmor

Le code source de ce blog est publié sur [GitHub]. Veuillez vous référer à l'environnement local de Mac pour l'environnement et Pipfile pour les bibliothèques requises.

Essayez en fait

Avant le cryptage

Voici le code avant le cryptage. [Single_Module] Après lecture du fichier image, le modèle VGG16 entraîné est utilisé pour la classification et l'affichage des images.

Single_Module/main.py


import os
import sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torch
from torchvision import models, transforms

sys.path.append(os.path.abspath('..'))
import imagenet_class


img = cv2.imread('../baseball.png')
img = cv2.resize(img, (256, 256))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_tensor = transforms.ToTensor()(img)
img_tensor = img_tensor.unsqueeze_(0)

model = models.vgg16(pretrained=True)

output = model(img_tensor)
output = np.argmax(output.detach().numpy())

print(imagenet_class.target[str(output)][1])   # ballplayer

plt.imshow(img)
plt.show()

スクリーンショット 2020-08-26 18.31.36.png

Vous pouvez voir que le résultat est également correctement classé comme «joueur de balle».

chiffrement

Cryptez avec la commande suivante.

$ pyarmor obfuscate main.py 

Après l'exécution, le répertoire dist sera créé directement en dessous. Le contenu du fichier est le suivant.

Cryptage sous licence

Comme vous pouvez le voir dans la section Génération de licence pour les scripts obfusqués de la documentation officielle, exécutez d'abord la commande suivante: (Nom librement tel que r001)

$ pyarmor licenses --expired 2022-01-01 r001

Ensuite, le répertoire licenses sera créé directement en dessous, et divers fichiers seront créés en dessous. Ensuite, comme précédemment, le fichier principal est chiffré avec la commande pyarmor obfuscate, mais il est exécuté avec les options suivantes.

$ pyarmor obfuscate --with-license licenses/r001/license.lic main.py

Ensuite, il est possible de crypter sous la forme d'une licence avec une date d'expiration. [Single_Module_Obfuscating_pre]

Exécution de fichiers cryptés

Le fichier principal chiffré peut être exécuté comme un script python normal. Le fichier principal chiffré jusqu'à présent existe directement sous le répertoire dist, donc le chemin relatif est légèrement différent de l'original. Par conséquent, afin d'aligner les chemins, j'ai fait une configuration comme [Single_Module_Obfuscating]. Je n'ai rien fait d'autre que de changer l'emplacement des fichiers. Essayez d'exécuter la commande suivante.

$ python main.py

【résultat】

[out] ballplayer

スクリーンショット 2020-08-26 18.31.36.png

Vous pouvez voir que le résultat est exactement le même qu'avant le chiffrement. Essayons également de voir à quoi ressemble le fichier principal essentiel.

$ cat main.py

from pytransform import pyarmor_runtime
pyarmor_runtime()
__pyarmor__(__name__, __file__, b'\x50\x59\x41\x52 ...(Omis ci-dessous)

Vous pouvez voir qu'il est normalement crypté de cette manière. Comme je l'ai mentionné plus tôt, la bibliothèque dynamique générée en même temps est toujours requise pour que ce fichier principal soit exécuté.

Lors de l'obscurcissement, y compris des fichiers .py sous différents répertoires

Par défaut, tous les fichiers .py situés directement en dessous sont chiffrés. Si vous souhaitez crypter récursivement tous les fichiers .py, y compris les sous-répertoires, exécutez avec les options suivantes.

$ pyarmor obfuscate --recursive main.py

Je vais essayer. [Whole_Module] est le code source avant le chiffrement, mais c'est le même qu'avant. (Séparez simplement les fichiers) Le main.py directement en dessous lit le model / model.py sous la sous-direction.

Whole_Module/model/model.py


from torch import nn
from torchvision import models


class SampleModel(nn.Module):
    def __init__(self):
        super(SampleModel, self).__init__()
        self.backborn = models.vgg16(pretrained=True)

    def forward(self, x):
        x = self.backborn(x)
        return x

Whole_Module/main.py


import os
import sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torch
from torchvision import transforms

from model.model import SampleModel
sys.path.append(os.path.abspath('..'))
import imagenet_class


img = cv2.imread('../baseball.png')
img = cv2.resize(img, (256, 256))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_tensor = transforms.ToTensor()(img)
img_tensor = img_tensor.unsqueeze_(0)

model = SampleModel()

output = model(img_tensor)
output = np.argmax(output.detach().numpy())

print(imagenet_class.target[str(output)][1])

plt.imshow(img)
plt.show()

Maintenant, lorsque vous exécutez la commande précédente, un nouveau répertoire dist sera créé et la bibliothèque chiffrée main.py, model.py et dynamique sera créée. [Whole_Module_Obfuscating_pre]. Cependant, comme il ne peut pas être exécuté pour la même raison qu'avant (le chemin relatif du fichier image est différent), le fichier généré a été déplacé. Cela peut également être exécuté sans aucun problème comme auparavant. [Whole_Module_Obfuscating]

Recommended Posts

PyArmor ~ Un moyen facile de chiffrer et de fournir du code source Python ~
Un moyen simple de vérifier la source des modules Python
Un moyen simple de personnaliser l'importation Python
Un moyen simple d'utiliser Wikipedia avec Python
Un moyen simple d'utiliser Python 2.7 sur Cent OS 6
Liste de code Python à déplacer et à mémoriser
Un moyen simple d'appeler Java depuis Python
Différences dans la façon d'écrire du code source externe entre Ruby et Python
Réécrire le code Python2 en Python3 (2to3)
Un moyen facile de gratter avec Python en utilisant Google Colab
Ce n'est pas facile d'écrire Python, c'est facile d'écrire numpy et scipy
API Nifty Cloud facile à utiliser avec botocore et python
Comment analyser le code source Java avec AST (Abstract Syntax Tree) en utilisant ANTLR et Python
Conseils pour coder courts et faciles à lire en Python
Un moyen standard de développer et de distribuer des packages en Python
[Python] Un moyen simple de visualiser les données énergétiques de manière interactive [plotly.express]
[Python] Une autre façon d'importer
Un moyen simple de renommer des fichiers
Installation source et installation de Python
Un moyen simple de visualiser le temps pris en Python et un moyen plus intelligent de l'améliorer
Convertir le code python 3.x en python 2.x
Un moyen simple d'accéder à l'API produit Amazon en Python
Faites fonctionner Jupyter avec l'API REST pour extraire et enregistrer le code Python
Un moyen facile d'arrondir après la virgule décimale en python3
[PEP8] Reprenez le code source Python et écrivez-le proprement
Code Python pour vérifier et représenter graphiquement s'il suit la loi de Benford
Comment créer un environnement d'exécution Python et Jupyter avec VSCode
Comment afficher les octets de la même manière en Java et Python
Python 3.6 sous Windows ... et vers Xamarin.
[Introduction à Python3 Jour 1] Programmation et Python
Bloc-notes Jupyter facile à utiliser (Python3.5)
Journalisation Python et vidage vers json
Sélénium et python pour ouvrir Google
Python facile à apprendre en écrivant
[Python] Lire le code source de Flask
[Tutoriel Python] Une introduction facile à Python
Un moyen simple de saisir et d'exécuter des cas de test AtCoder dans Jupyter Notebook
Exemple de code pour obtenir oauth_token et oauth_token_secret de l'API Twitter en Python 2.7
Essayez d'écrire du code python pour générer du code go - Essayez de porter JSON-to-Go et ainsi de suite
Code Python pour former et tester avec Custom Vision of Cognitive Service
Installation du code Visual Studio et installation de python
De Python à l'utilisation de MeCab (et CaboCha)
Comment installer et utiliser pandas_datareader [Python]
python> lien> Comportement / code de Strftime () et strptime ()
Lier des méthodes aux classes et instances Python
Obtenez des métriques de code source Python à l'aide de radon
Fractal pour faire et jouer avec Python
Portage et modification du solveur de doublets de python2 vers python3.
Lire Python csv et exporter vers txt
python: Comment utiliser les locals () et globals ()
Flux du code source à la création du format d'exécution
Crypter avec Ruby (Rails) et décrypter avec Python
[Python] Comment calculer MAE et RMSE
Comment utiliser le zip Python et énumérer
Compressez les données python et écrivez sur sqlite
Introduction facile de la série python3 et d'OpenCV3
Scraping Web facile avec Python et Ruby
Comment utiliser is et == en Python