Vérification sécurisée de fichiers avec Ruby et SHA384
Pour vérifier un téléchargement en Ruby, calculez l’empreinte SHA384 de ses octets avec OpenSSL et comparez le résultat à une somme de contrôle de confiance. Le script ci-dessous accepte une ou plusieurs paires fichier/somme de contrôle et renvoie un code de sortie non nul si une vérification échoue, ce qui vous permet de l’utiliser dans une tâche automatisée.
Partir d’une somme de contrôle de confiance
SHA-384 appartient à la famille SHA-2 et produit une empreinte de 384 bits : 48 octets, soit 96 caractères hexadécimaux. Utilisez-le lorsque votre éditeur ou votre flux de travail existant fournit des sommes de contrôle SHA384 ; une référence calculée avec SHA256 ne peut pas être vérifiée avec SHA384.
Obtenez la somme de contrôle attendue auprès d’une source de confiance, comme la page de version de l’éditeur servie en HTTPS authentifié ou un manifeste de sommes de contrôle signé dont vous avez vérifié la signature. Si quelqu’un peut remplacer à la fois le fichier et sa somme de contrôle de référence, il peut faire réussir votre vérification. Le hachage détecte les modifications par rapport à cette référence ; il ne rend pas un fichier infalsifiable et n’établit pas qu’il peut être exécuté sans risque. La documentation OpenSSL de Ruby explique comment les empreintes entrent aussi dans la composition des signatures numériques.
Vérifier Ruby et OpenSSL
Il vous faut Ruby avec son extension OpenSSL. Les commandes présentées ici ont été testées sous Linux
avec Ruby 3.4.10, Ruby/OpenSSL 3.3.3 et OpenSSL 3.6.4. Les exemples shell utilisent Bash ;
sha384sum de GNU Coreutils est facultatif pour la comparaison indépendante
ci-dessous. Si Ruby n’est pas installé, suivez le
guide d’installation de Ruby officiel pour votre plateforme.
Vérifiez l’interpréteur, la bibliothèque liée et la disponibilité de SHA384 avant de continuer :
ruby -ropenssl -e 'puts RUBY_DESCRIPTION; puts "Ruby/OpenSSL #{OpenSSL::VERSION}"; puts OpenSSL::OPENSSL_LIBRARY_VERSION; puts "SHA384: #{OpenSSL::Digest.new("SHA384").digest_length} bytes"'
La dernière ligne doit être SHA384: 48 bytes. Si le chargement d’OpenSSL ou la création
de l’empreinte échoue, corrigez votre installation de Ruby avant d’exécuter le vérificateur. La
commande openssl de votre PATH peut utiliser une autre bibliothèque que Ruby :
sa version seule ne prouve donc pas que ce prérequis est satisfait.
Enregistrer le vérificateur
Enregistrez ce script complet sous le nom verify_sha384.rb. Il lit chaque fichier par
blocs de 8 KiB et réutilise le tampon, de sorte qu’il ne charge pas le fichier entier en mémoire. La
méthode IO#read de Ruby renvoie
nil en fin de fichier lorsqu’elle reçoit une longueur positive, y compris
pour un fichier vide. Chaque bloc est transmis à
OpenSSL::Digest#update.
require 'openssl'
def sha384_hash(path)
digest = OpenSSL::Digest.new('SHA384')
File.open(path, 'rb') do |file|
buffer = ''.b
digest.update(buffer) while file.read(8192, buffer)
end
digest.hexdigest
end
if ARGV.empty? || ARGV.length.odd?
warn 'Usage: ruby verify_sha384.rb FILE SHA384 [FILE SHA384 ...]'
exit 2
end
failed = false
ARGV.each_slice(2) do |path, expected|
unless /\A[0-9a-fA-F]{96}\z/.match?(expected)
warn "#{path}: ERROR (expected 96 hexadecimal characters)"
failed = true
next
end
begin
actual = sha384_hash(path)
if actual == expected.downcase
puts "#{path}: OK"
else
warn "#{path}: FAILED (SHA384 mismatch)"
failed = true
end
rescue SystemCallError, IOError => error
warn "#{path}: ERROR (#{error.message})"
failed = true
end
end
exit(failed ? 1 : 0)
Transmettez l’empreinte seule, sans nom de fichier, sans préfixe sha384- ni
espaces autour. Les lettres hexadécimales majuscules sont acceptées. Le script compare des sommes de
contrôle publiques avec == ; dans ce flux de travail, aucune somme de
contrôle secrète n’est à protéger contre une fuite par mesure du temps. Pour les authentificateurs
secrets comme les HMAC, Ruby fournit des
méthodes de comparaison à temps constant plutôt que d’exiger une
boucle de comparaison écrite à la main.
Vérifier un fichier dont le résultat est connu
Dans un répertoire de travail temporaire contenant verify_sha384.rb, exécutez les
commandes suivantes dans Bash. Elles créent example.txt contenant exactement les
trois octets abc, sans saut de ligne final. La création refuse d’écraser
un fichier existant ; en cas d’échec, la chaîne && s’arrête avant la
vérification. Utilisez un autre répertoire temporaire si vous souhaitez refaire la préparation.
ruby -e 'File.open("example.txt", "wbx") { |file| file.write("abc") }' &&
EXPECTED_SHA384='cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7' &&
ruby verify_sha384.rb example.txt "$EXPECTED_SHA384"
Le résultat est :
example.txt: OK
La commande se termine avec le code 0. Pour votre propre téléchargement,
indiquez son chemin et la somme de contrôle SHA384 de confiance de cette version précise. Mettez entre
guillemets les chemins contenant des espaces. Le vérificateur ouvre les fichiers en lecture seule et
ne crée aucun artefact de vérification.
Si vous disposez de GNU Coreutils, calculez indépendamment la somme de contrôle de l’exemple avec
sha384sum :
sha384sum --binary -- example.txt
Son premier champ doit être égal à EXPECTED_SHA384. Calculer un hachage à partir d’un
fichier que vous venez de télécharger est utile pour comparer, mais ne vous fournit pas à lui seul
une référence de confiance pour ce téléchargement.
Faire échouer la tâche quand un lot échoue
Continuez dans la même session Bash pour que EXPECTED_SHA384 reste défini. Créez un
fichier vide et vérifiez les deux exemples en passant une autre paire fichier/somme de contrôle :
ruby -e 'File.open("empty.bin", "wbx") {}' &&
EMPTY_SHA384='38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b' &&
ruby verify_sha384.rb example.txt "$EXPECTED_SHA384" empty.bin "$EMPTY_SHA384"
Les deux fichiers doivent afficher OK, et la commande se termine avec
0. La création de empty.bin refuse elle aussi une
destination existante. Ajoutez maintenant un saut de ligne au premier exemple, qui est jetable, et
relancez le lot :
ruby -e 'File.open("example.txt", "ab") { |file| file.write("\n") }' &&
ruby verify_sha384.rb example.txt "$EXPECTED_SHA384" empty.bin "$EMPTY_SHA384"
example.txt affiche FAILED (SHA384 mismatch) sur la sortie d’erreur
standard, tandis que empty.bin affiche toujours
OK sur la sortie standard. Le lot se termine avec
1 : un succès ultérieur ne peut pas effacer un échec antérieur. Le
script vérifie chaque paire fournie et ne réécrit aucune des deux sommes de contrôle de référence.
Les codes de sortie sont 0 lorsque chaque fichier correspond,
1 lorsqu’un fichier ne correspond pas, a une somme de contrôle attendue
mal formée ou ne peut pas être lu, et 2 lorsque la liste de paires est
absente ou incomplète. Dans une tâche, faites du vérificateur la dernière commande de son étape, ou
propagez explicitement son code de sortie non nul avant d’exécuter d’autres commandes. Afficher un
message d’erreur ne suffit pas à faire échouer une tâche shell.
Diagnostiquer une vérification échouée
- 96 caractères hexadécimaux attendus : copiez uniquement l’empreinte SHA384. Une somme de
contrôle SHA256, une valeur Base64 ou une ligne de sortie
sha384sumentière n’est pas un argument valide. - Discordance SHA384 : vérifiez la version, le nom de fichier, l’intégralité du téléchargement et l’algorithme attendu. Ne remplacez pas la référence par la nouvelle empreinte dans le seul but de faire réussir la vérification.
- Erreur de fichier ou d’autorisation : vérifiez le répertoire de travail, le chemin et les
droits de lecture du compte qui exécute la tâche. Une lecture échouée renvoie
1même si d’autres fichiers passent la vérification.
Préserver les octets que vous voulez vérifier
Le mode binaire préserve les octets transmis au calcul de l’empreinte. La
documentation sur les modes de fichier
de Ruby décrit comment 'b' désactive la conversion des sauts de ligne sous
Windows. Il ne rend pas identiques un fichier LF et un fichier CRLF : ces fichiers contiennent des
octets différents et devraient avoir des sommes de contrôle différentes. Évitez de normaliser les
fins de ligne, de supprimer des espaces ou de réencoder le texte avant cette vérification. Ces
opérations vérifieraient un contenu transformé au lieu du fichier téléchargé.
Utilisez des fichiers ordinaires entièrement écrits qui resteront inchangés pendant la vérification et l’utilisation qui suit. Ce petit outil CLI ne verrouille pas les fichiers et n’empêche pas un autre processus de les remplacer après une vérification réussie. Protégez la référence de confiance, ainsi que le fichier que vous avez vérifié.
Pour calculer des empreintes dans un flux de travail Transloadit, consultez la documentation de /file/hash (English). La même exigence de référence de confiance s’applique lorsqu’une somme de contrôle est générée pendant le traitement des fichiers.
