読者です 読者をやめる 読者になる 読者になる

色々でべろっぷ

WordPress、サーバー構築、プログラム等のメモ

Javaでチェックサムファイルを生成する(SHA-256)

インターネット経由でファイルをダウンロードしたときに、
チェックサムファイルを用いて、ファイルの破損チェック、改竄チェックを行うことがある

package net.shina_ken.test.checksum;
 
import java.io.File;
import java.io.IOException;
 
//使い方:チェックサムファイル作成
//1. download.csvからメッセージダイジェストを
// 生成する(SHA256のアルゴリズム)
//2. 生成したメッセージダイジェストを
// download.sumとしてファイルに書きこむ
 
public class Checksum {
 public static void main(String[] args){
  File csvFile = new File("test.txt");
  File sumFile = new File("checksum.txt");
  try {
   ChecksumUtil.createChecksumFile(csvFile, sumFile);
  } catch (IOException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (Exception e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  }
 }
}



package net.shina_ken.test.checksum;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.MessageDigest;
 
public class ChecksumUtil {
 /** Algorithm */
 private static final String ALGORITHM = "SHA256";
 
 /**
  * チェックサムファイルを生成します。
  * @param src 生成元のファイル
  * @param sum 生成するチェックサムファイル
  */
 public static void createChecksumFile(File src, File sum)
   throws IOException, Exception {
 
  String sRecord = printDigest(getFileDigest(src));
 
  PrintStream ps = null;
  try {
   // Streamを作成します。
   ps = new PrintStream(
     new FileOutputStream(sum)
     , false
     , "windows-31j"
     );
   ps.println(sRecord);
  } catch (IOException e) {
   throw e;
  } finally {
   if (ps != null) {
    try {ps.flush();} catch (Exception e) {}
    try {ps.close();} catch (Exception e) {}
   }
  }
 }
 
 /**
  * ファイルからダイジェストを生成します。
  * @param path ダイジェストを生成するファイル
  * @return ダイジェスト(16進数)
  */
 public static byte[] getFileDigest(File path)
   throws Exception {
 
  // ファイルの中身からダイジェストを生成する
  MessageDigest md =
    MessageDigest.getInstance(ALGORITHM);
 
  FileInputStream in = null;
  try {
   in = new FileInputStream(path);
 
   // dat配列の先頭からlenまでのダイジェストを計算する
   byte[] dat = new byte[256];
   int len;
   while ((len = in.read(dat)) >= 0) {
    md.update(dat, 0, len);
   }
  } finally {
   if (in != null) {
    try{in.close();} catch (Exception e){}
   }
  }
  return md.digest();
 }
 
 /**
  * ダイジェスト(16進数)からダイジェスト(文字列)を生成します。
  * @param digest ダイジェスト(16進数)
  * @return ダイジェスト(文字列)
  */
 public static String printDigest(byte[] digest) {
  String sSum = "";
  for (int i = 0; i < digest.length; i++) {
 
   // byte型では128~255が負値になっているので補正
   int d = digest[i];
   if (d < 0) {
    d += 256;
   }
 
   // 0~15は16進数で1桁のため、2桁になるよう頭に0を追加
   if (d < 16) {
    sSum += "0";
   }
   sSum += Integer.toString(d, 16);
  }
 
  return sSum;
 }
}