各言語でメッセージダイジェスト
手元にある各言語で、メッセージダイジェストを出力してみたメモ。
要件は以下の通り。
- 標準入力から、0バイト以上の任意のバイト列が入力される
- 標準出力に、入力に対する以下のハッシュ文字列を改行区切りで出力する
環境
手元にあるものということで、環境は以下のものに限定する。
- CentOS 7
入力
Hello World!
出力
8ddd8be4b179a529afa5f2ffae4b9858 a0b65939670bc2c010f4d5d6a0b3e4e4590fb92b de9d76f0f6a015ab6629138a42835e7b44571995e4abb291c0817261 03ba204e50d126e4674c005e04d82e84c21366780af1f43bd54a37816b6ab340 07f60df0b95043b3a3717638e7776ab76ebaa4fc705ba659063229cf162980c04a9f7496dcda50de6510d40fde3eba8a 830445e86a0cfafac4e1531002356f384847a11a7456fb8ccb81ab36e37bff28f34fa2c5bfdd347e964c5c5df0fc305de6394368219307b2ceeb0ec84b7c2b31
Java
import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Main { public static void main(String[] args) throws NoSuchAlgorithmException { MessageDigest[] mdAry = { MessageDigest.getInstance("MD5"), MessageDigest.getInstance("SHA-1"), MessageDigest.getInstance("SHA-224"), MessageDigest.getInstance("SHA-256"), MessageDigest.getInstance("SHA-384"), MessageDigest.getInstance("SHA-512"), }; try (InputStream in = new BufferedInputStream(System.in)) { byte[] b = new byte[1024]; int len; while ((len = in.read(b)) > 0) { for (MessageDigest md : mdAry) { md.update(b, 0, len); } } } catch (IOException e) { e.printStackTrace(); } for (MessageDigest md : mdAry) { byte[] digest = md.digest(); for (byte b : digest) { System.out.printf("%02x", b); } System.out.println(); } } }
C
#include <stdio.h> #include <string.h> #include <openssl/md5.h> #include <openssl/sha.h> int main(int argc, char** argv) { MD5_CTX md5_ctx; unsigned char md5[MD5_DIGEST_LENGTH]; SHA_CTX sha1_ctx; unsigned char sha1[SHA_DIGEST_LENGTH]; SHA256_CTX sha224_ctx; unsigned char sha224[SHA224_DIGEST_LENGTH]; SHA256_CTX sha256_ctx; unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA512_CTX sha384_ctx; unsigned char sha384[SHA384_DIGEST_LENGTH]; SHA512_CTX sha512_ctx; unsigned char sha512[SHA512_DIGEST_LENGTH]; if (!MD5_Init(&md5_ctx)) { return 1; } if (!SHA1_Init(&sha1_ctx)) { return 1; } if (!SHA224_Init(&sha224_ctx)) { return 1; } if (!SHA256_Init(&sha256_ctx)) { return 1; } if (!SHA384_Init(&sha384_ctx)) { return 1; } if (!SHA512_Init(&sha512_ctx)) { return 1; } char buf[1024]; int len; while ((len = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) { if (!MD5_Update(&md5_ctx, buf, len)) { return 1; } if (!SHA1_Update(&sha1_ctx, buf, len)) { return 1; } if (!SHA224_Update(&sha224_ctx, buf, len)) { return 1; } if (!SHA256_Update(&sha256_ctx, buf, len)) { return 1; } if (!SHA384_Update(&sha384_ctx, buf, len)) { return 1; } if (!SHA512_Update(&sha512_ctx, buf, len)) { return 1; } } if (!MD5_Final(md5, &md5_ctx)) { return 1; } if (!SHA1_Final(sha1, &sha1_ctx)) { return 1; } if (!SHA224_Final(sha224, &sha224_ctx)) { return 1; } if (!SHA256_Final(sha256, &sha256_ctx)) { return 1; } if (!SHA384_Final(sha384, &sha384_ctx)) { return 1; } if (!SHA512_Final(sha512, &sha512_ctx)) { return 1; } for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", md5[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha1[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA224_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha224[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha256[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA384_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha384[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA512_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha512[i]); } fprintf(stdout, "\n"); return 0; }
「-lcrypto」を付けてコンパイルする必要がある。
C++
C言語と大して変わらないけど、一応載せておく。
#include <cstdio> #include <string> #include <openssl/md5.h> #include <openssl/sha.h> int main(int argc, char** argv) { MD5_CTX md5_ctx; unsigned char md5[MD5_DIGEST_LENGTH]; SHA_CTX sha1_ctx; unsigned char sha1[SHA_DIGEST_LENGTH]; SHA256_CTX sha224_ctx; unsigned char sha224[SHA224_DIGEST_LENGTH]; SHA256_CTX sha256_ctx; unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA512_CTX sha384_ctx; unsigned char sha384[SHA384_DIGEST_LENGTH]; SHA512_CTX sha512_ctx; unsigned char sha512[SHA512_DIGEST_LENGTH]; if (!MD5_Init(&md5_ctx)) { return EXIT_FAILURE; } if (!SHA1_Init(&sha1_ctx)) { return EXIT_FAILURE; } if (!SHA224_Init(&sha224_ctx)) { return EXIT_FAILURE; } if (!SHA256_Init(&sha256_ctx)) { return EXIT_FAILURE; } if (!SHA384_Init(&sha384_ctx)) { return EXIT_FAILURE; } if (!SHA512_Init(&sha512_ctx)) { return EXIT_FAILURE; } char buf[1024]; int len; while ((len = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) { if (!MD5_Update(&md5_ctx, buf, len)) { return EXIT_FAILURE; } if (!SHA1_Update(&sha1_ctx, buf, len)) { return EXIT_FAILURE; } if (!SHA224_Update(&sha224_ctx, buf, len)) { return EXIT_FAILURE; } if (!SHA256_Update(&sha256_ctx, buf, len)) { return EXIT_FAILURE; } if (!SHA384_Update(&sha384_ctx, buf, len)) { return EXIT_FAILURE; } if (!SHA512_Update(&sha512_ctx, buf, len)) { return EXIT_FAILURE; } } if (!MD5_Final(md5, &md5_ctx)) { return EXIT_FAILURE; } if (!SHA1_Final(sha1, &sha1_ctx)) { return EXIT_FAILURE; } if (!SHA224_Final(sha224, &sha224_ctx)) { return EXIT_FAILURE; } if (!SHA256_Final(sha256, &sha256_ctx)) { return EXIT_FAILURE; } if (!SHA384_Final(sha384, &sha384_ctx)) { return EXIT_FAILURE; } if (!SHA512_Final(sha512, &sha512_ctx)) { return EXIT_FAILURE; } for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", md5[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha1[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA224_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha224[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha256[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA384_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha384[i]); } fprintf(stdout, "\n"); for (int i = 0; i < SHA512_DIGEST_LENGTH; ++i) { fprintf(stdout, "%02x", sha512[i]); } fprintf(stdout, "\n"); return EXIT_SUCCESS; }
「-lcrypto」を付けてコンパイルする必要がある。
PHP
<?php $input = file_get_contents('php://stdin'); printf("%s\n", hash('md5', $input)); printf("%s\n", hash('sha1', $input)); printf("%s\n", hash('sha224', $input)); printf("%s\n", hash('sha256', $input)); printf("%s\n", hash('sha384', $input)); printf("%s\n", hash('sha512', $input));
メモリに載りきらないほどのデータが来たら対応できないのが難点。
Python 2
import sys import hashlib md5 = hashlib.md5() sha1 = hashlib.sha1() sha224 = hashlib.sha224() sha256 = hashlib.sha256() sha384 = hashlib.sha384() sha512 = hashlib.sha512() while True: line = sys.stdin.readline() if line == '': break md5.update(line) sha1.update(line) sha224.update(line) sha256.update(line) sha384.update(line) sha512.update(line) print md5.hexdigest() print sha1.hexdigest() print sha224.hexdigest() print sha256.hexdigest() print sha384.hexdigest() print sha512.hexdigest()
Python 3
import sys import hashlib md5 = hashlib.md5() sha1 = hashlib.sha1() sha224 = hashlib.sha224() sha256 = hashlib.sha256() sha384 = hashlib.sha384() sha512 = hashlib.sha512() while True: line = sys.stdin.buffer.readline() if line == b'': break md5.update(line) sha1.update(line) sha224.update(line) sha256.update(line) sha384.update(line) sha512.update(line) print(md5.hexdigest()) print(sha1.hexdigest()) print(sha224.hexdigest()) print(sha256.hexdigest()) print(sha384.hexdigest()) print(sha512.hexdigest())
Ruby
require 'openssl' mdAry = [ OpenSSL::Digest.new("md5"), OpenSSL::Digest.new("sha1"), OpenSSL::Digest.new("sha224"), OpenSSL::Digest.new("sha256"), OpenSSL::Digest.new("sha384"), OpenSSL::Digest.new("sha512"), ] while line = STDIN.gets for md in mdAry md.update(line) end end for md in mdAry puts md.hexdigest end
Perl
use Digest::MD5; use Digest::SHA; my $md5 = Digest::MD5->new(); my $sha1 = Digest::SHA->new("sha1"); my $sha224 = Digest::SHA->new("sha224"); my $sha256 = Digest::SHA->new("sha256"); my $sha384 = Digest::SHA->new("sha384"); my $sha512 = Digest::SHA->new("sha512"); while (my $line = readline(STDIN)) { $md5->add($line); $sha1->add($line); $sha224->add($line); $sha256->add($line); $sha384->add($line); $sha512->add($line); } print $md5->hexdigest(),"\n"; print $sha1->hexdigest(),"\n"; print $sha224->hexdigest(),"\n"; print $sha256->hexdigest(),"\n"; print $sha384->hexdigest(),"\n"; print $sha512->hexdigest(),"\n";
「yum install perl-Digest-MD5 perl-Digest-SHA」が必要。
Go
package main import ( "fmt" "io" "os" "crypto/md5" "crypto/sha1" "crypto/sha256" "crypto/sha512" ) func main() { aMd5 := md5.New() aSha1 := sha1.New() aSha224 := sha256.New224() aSha256 := sha256.New() aSha384 := sha512.New384() aSha512 := sha512.New() for { buf := make([]byte, 1024) n, err := os.Stdin.Read(buf) if err == io.EOF { break } buf2 := make([]byte, 0); buf2 = append(buf2, buf[0:n]...) aMd5.Write(buf2) aSha1.Write(buf2) aSha224.Write(buf2) aSha256.Write(buf2) aSha384.Write(buf2) aSha512.Write(buf2) } fmt.Printf("%x\n", aMd5.Sum(nil)) fmt.Printf("%x\n", aSha1.Sum(nil)) fmt.Printf("%x\n", aSha224.Sum(nil)) fmt.Printf("%x\n", aSha256.Sum(nil)) fmt.Printf("%x\n", aSha384.Sum(nil)) fmt.Printf("%x\n", aSha512.Sum(nil)) }
- md5 - The Go Programming Language
- sha1 - The Go Programming Language
- sha256 - The Go Programming Language
- sha512 - The Go Programming Language
bash
#! /bin/bash cat | tee \ >(sha512sum | cut -d " " -f 1) \ >(sha384sum | cut -d " " -f 1) \ >(sha256sum | cut -d " " -f 1) \ >(sha224sum | cut -d " " -f 1) \ >(sha1sum | cut -d " " -f 1) \ >(md5sum | cut -d " " -f 1) \ >> /dev/null
バイナリデータのテストケースにも対応するためにteeコマンド+コマンド置換を使ったが、期待する順番通りに出力されないことがあるのが難点。
man md5sum
man sha1sum
man sha224sum
man sha256sum
man sha384sum
man sha512sum