Hash(MDx, SHA-xxx)
MD5を使う機会があったので、色々な言語での求め方を調べてみた。
Uinux系
md5
, md5sum
が使えれば↓でおk
md5sum <file> md5 <file> md5 -s <text>
brewでインストールするなら、
brew install md5sha1sum
shasum
もついてくる。
shasum [OPTION]... [FILE]... With no FILE, or when FILE is -, read standard input. -a, --algorithm 1 (default), 224, 256, 384, 512, 512224, 512256
Objective-C
長さCC_MD5_DIGEST_LENGTH
のバッファmd
を用意して、
unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)
に渡すだけ。
巨大なバイト列を分割して処理する場合は、
int CC_MD5_Init(CC_MD5_CTX *c); int CC_MD5_Update(CC_MD5_CTX *c, const void *data, CC_LONG len); int CC_MD5_Final(unsigned char *md, CC_MD5_CTX *c);
を使う。
他のハッシュアルゴリズムを使う場合はMD5
の部分を変える。
用意されているアルゴリズムは、
MD2
, MD4
, MD5
, SHA1
, SHA224
, SHA256
, SHA384
, SHA512
#import <CommonCrypto/CommonDigest.h> NSString* convertDigest(unsigned char *digest, int digestLength) { NSMutableString *ret = [NSMutableString stringWithCapacity:digestLength * 2]; for(int i = 0; i < digestLength; ++i) [ret appendFormat:@"%02x", digest[i]]; return ret; } NSString* MD5Hash(const void *data, NSUInteger len) { unsigned char md[CC_MD5_DIGEST_LENGTH]; CC_MD5(data, (CC_LONG)len, md); return convertDigest(md, CC_MD5_DIGEST_LENGTH); } NSString* MD5HashArray(const void *datas[], NSArray *lenArray) { unsigned char md[CC_MD5_DIGEST_LENGTH]; CC_MD5_CTX ctx; CC_MD5_Init(&ctx); for (int i = 0; i < lenArray.count; ++i) CC_MD5_Update(&ctx, datas[i], (CC_LONG)[((NSNumber*)(lenArray[i])) unsignedIntegerValue]); CC_MD5_Final(md, &ctx); return convertDigest(md, CC_MD5_DIGEST_LENGTH); } #pragma mark - MD5 test static const NSString * const str = @"D364D54F-597E-4375-B329-2DE3B2E3539D"; static const char * const strs[] = { "D364D54F-", "597E-4375-", "B329-2DE3B2E3539D" }; static const int N = sizeof(strs)/sizeof(strs[0]); void testMD5(void) { NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"%@\n%@\n", MD5Hash([str UTF8String], str.length), MD5Hash(data.bytes, data.length)); NSMutableArray *lenArray = [NSMutableArray arrayWithCapacity:N*2]; for (int i = 0; i < N; ++i) [lenArray addObject:@(strlen(strs[i]))]; NSLog(@"%@", MD5HashArray((const void**)strs, lenArray)); }
Perl
# 関数形式 use Digest::MD5 qw(md5 md5_hex md5_base64); $digest = md5($data); $digest = md5_hex($data); $digest = md5_base64($data); # OO 形式 use Digest::MD5; $ctx = Digest::MD5->new; $ctx->add($data); $ctx->addfile(*FILE); $digest = $ctx->digest; $digest = $ctx->hexdigest; $digest = $ctx->b64digest;
OO形式を使えば、ファイル指定や分割して渡すこともできる。
#ファイル指定 open my $fh, '<', $filepath or die "Cannot open '$filepath': $!"; my $md5 = Digest::MD5->new->addfile($fh)->hexdigest;
#ブロック分割 my $md5 = Digest::MD5->new; while (<FILE>) { $md5->add($_); } my $md5str = $md5->b64digest;
他のアルゴリズムだいたい同じ感じ、 SHAxxxの場合、new でxxxを指定できる。 CPAN
use Digest::SHA my $alg = 256; my $sha = Digest::SHA->new($alg)->addfile($fh)->hexdigest;
Java
java.security.MessageDigest
を使う。
getInstance(alg)
でアルゴリズムを指定して、インスタンスを作る。
digest(byte[])
でハッシュ結果がbyte配列で得られる。
ブロック分割する場合は、update()
を使う。
MD2
, MD5
, SHA
, SHA-256
, SHA-384
, SHA-512
が使えるみたい。
import java.io.*; import java.security.*; public class HashTest { static public String hashWithAlgorihtm(String algorithm, byte[] data) throws NoSuchAlgorithmException { return convertDigest(MessageDigest.getInstance(algorithm).digest(data)); } static public String hashWithAlgorithm(String algorithm, InputStream in) throws NoSuchAlgorithmException, IOException { MessageDigest md = MessageDigest.getInstance(algorithm); byte[] buff = new byte[1024]; for (int len = 0;(len = in.read(buff, 0, buff.length)) >= 0; md.update(buff, 0, len)); return convertDigest(md.digest()); } static private String convertDigest(byte[] digest) { StringBuilder sb = new StringBuilder(digest.length * 2); for (byte b : digest) { String s = Integer.toHexString(b & 0xff); if (s.length() == 1) sb.append("0"); sb.append(s); } return sb.toString(); } static final String test = "D364D54F-597E-4375-B329-2DE3B2E3539D", fname = "test.txt"; static void test(String algorithm) { try (FileInputStream in = new FileInputStream(fname)) { System.out.println(hashWithAlgorihtm(algorithm, test.getBytes())); System.out.println(hashWithAlgorithm(algorithm, in)); } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } } public static void main(String[] args) { try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(fname)))) { pw.print(test); } catch (IOException e) { e.printStackTrace(); } test("md5"); } }
C/C++
詳しく調べてないですが、Open SSLとかCrypto++を使えば良さそうです。
現バージョンのboostにはなかった... ※Boost.Uuidにsha1クラスがあるので、sha1だけなら作れるみたい。 http://nukesaq88.hatenablog.com/entry/2013/04/19/183424