Xorcism

Xorcism

Difficile

Instructions

Écris un adaptateur de flux qui contient une référence vers une clé et qui lui applique un XOR bit à bit avec des données arbitraires.

XOR est une opération binaire fondamentale : pour chaque bit des entrées, on met le bit correspondant de la sortie à 1 si les bits d'entrée sont différents. Si les deux entrées valent 1 ou si les deux valent 0, alors le bit de sortie correspondant est 0.

Lorsqu'on applique un XOR entre un document et une clé, la clé est répétée autant de fois que nécessaire, ce qui produit un document de sortie de même longueur que le document d'entrée.

Le XOR entre un document et une clé a servi en cryptographie, et ce jusqu'au début du XXe siècle. Si cette méthode est complètement obsolète pour cacher des données, elle peut être étonnamment utile pour générer des données bruitées qui semblent aléatoires, sans avoir à se compliquer la vie avec du vrai hasard. Elle sert encore ponctuellement dans la cryptographie moderne, pour certains chiffrements : le chiffrement lui-même n'est qu'un mécanisme qui génère une clé très aléatoire et infiniment longue, que l'on combine par XOR avec le document.

Une propriété intéressante du chiffrement par XOR est sa symétrie : le XOR d'un nombre avec lui-même donne 0, et le XOR d'un nombre avec 0 renvoie le nombre d'entrée inchangé. Par conséquent, pour déchiffrer un document qui a été chiffré par XOR, il suffit de le rechiffrer par XOR avec la même clé.

Pas d'allocation

Il n'est pas réaliste d'écrire un test qui vérifie que ta structure contient une référence vers la clé plutôt qu'une copie de celle-ci. De même, il n'est pas réaliste de démontrer par un test que ni munge ni munge_in_place, ni aucune de leurs fonctions auxiliaires, n'alloue sur le tas. Tu devrais tout de même essayer d'écrire ta solution de cette façon.

Implémentation

Tu vas devoir écrire une struct Xorcism qui contient une référence vers une clé. Cette structure doit fournir deux méthodes : munge_in_place et munge. La première modifie un tampon d'octets sur place. La seconde est un adaptateur d'itérateur : elle prend un itérateur de données quelconque et renvoie un nouvel itérateur de données.

Les signatures fournies dans le squelette de cet exercice sont en grande partie correctes sur le plan syntaxique, mais elles ne compilent pas : une bonne partie de l'intérêt de cet exercice est de te familiariser avec l'utilisation des durées de vie et des génériques, tu vas donc devoir les compléter toi-même. Cet exercice a aussi pour but de te faire trouver une factorisation adaptée qui te permette d'implémenter ces deux méthodes avec un minimum de duplication d'effort. N'hésite pas à ajouter des fonctions auxiliaires !

Traits utiles

Ces traits te seront utiles :

Tests bonus

Cet exercice contient des tests bonus, cachés derrière la fonctionnalité io. Pour les activer, exécute

cargo test --features io

Pour ces tests, tu devras implémenter une méthode reader avec la signature

fn reader(self, impl Read) -> impl Read

et une méthode writer avec la signature

fn writer(self, impl Write) -> impl Write

Ces fonctions convertissent chacune la structure Xorcism en adaptateur de flux dans la direction appropriée. Elles utilisent les traits suivants :

Durée de vie de la valeur de retour de munge

En raison de l'utilisation de la fonctionnalité impl Trait, la gestion des durées de vie peut être un peu délicate lors de l'implémentation de la méthode munge. On peut trouver plus simple d'écrire sa propre struct avec une implémentation de Iterator et de renvoyer ce type concret, au moins pour commencer. Au final, c'est une bonne idée d'essayer d'implémenter la solution en utilisant directement les combinateurs de Iterator.


Source

Peter Goodspeed-Niklaus
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Rust Exercism

Prêt à commencer Xorcism ?

Inscris-toi sur Exercism pour apprendre et maîtriser Rust avec 99 exercices, et un vrai mentorat humain, le tout gratuitement.