手元にある各言語で、メッセージダイジェストを出力してみたメモ。
要件は以下の通り。
- 標準入力から、0バイト以上の任意のバイト列が入力される
- 標準出力に、入力に対する以下のハッシュ文字列を改行区切りで出力する
- MD5
- SHA-1
- SHA-224
- SHA-256
- SHA-384
- SHA-512
環境
手元にあるものということで、環境は以下のものに限定する。
入力
Hello World!
出力
8ddd8be4b179a529afa5f2ffae4b9858
a0b65939670bc2c010f4d5d6a0b3e4e4590fb92b
de9d76f0f6a015ab6629138a42835e7b44571995e4abb291c0817261
03ba204e50d126e4674c005e04d82e84c21366780af1f43bd54a37816b6ab340
07f60df0b95043b3a3717638e7776ab76ebaa4fc705ba659063229cf162980c04a9f7496dcda50de6510d40fde3eba8a
830445e86a0cfafac4e1531002356f384847a11a7456fb8ccb81ab36e37bff28f34fa2c5bfdd347e964c5c5df0fc305de6394368219307b2ceeb0ec84b7c2b31
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言語と大して変わらないけど、一応載せておく。
#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
$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));
メモリに載りきらないほどのデータが来たら対応できないのが難点。
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()
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())
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
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))
}
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