2016-01-31

Java でメッセージダイジェストを生成

Java の MessageDigest クラスは、MD5 あるいは SHA などのメッセージダイジェストアルゴリズムの機能を提供しています。

以前、bitWalk's: MD5 & SHA Checksum Utility で Windows 上で動作する MD5 & SHA Checksum Utility を紹介しましたが、Java で同じようなことを実現してみようと思い、簡単なサンプルを JavaFX で作ってみました。なお、MessageDigest クラスの使い方は、参考サイト [1] を参考にさせていただきました。

動作を確認した環境は次の通りです。

  • OS: Fedora 23 (x86_64)
  • Java: Java SE 1.8.0_72 (jdk1.8.0_72-1.8.0_72-fcs.x86_64)
  • IDE: NetBeans IDE 8.1

サンプルプログラムを以下に示しました。参考サイト [2] の GitHub にイメージを含む全ソースをアップしてあります。

package hashcalc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.xml.bind.DatatypeConverter;

public class HashCalc extends Application {

    String baseDir = getClass().getResource("image/").toString();
    Image icoApp = new Image(baseDir + "Binary.png");
    Image icoFile = new Image(baseDir + "File.png");
    Image icoPen = new Image(baseDir + "Pencil.png");

    File file;
    TextField field_sha256;

    @Override
    public void start(Stage primaryStage) {

        BorderPane root = new BorderPane();
        Scene scene = new Scene(root);

        GridPane gridpane = new GridPane();
        gridpane.setPadding(new Insets(5));
        gridpane.setHgap(5);
        gridpane.setVgap(2);

        ColumnConstraints column1 = new ColumnConstraints();
        ColumnConstraints column2 = new ColumnConstraints(600);
        ColumnConstraints column3 = new ColumnConstraints();
        gridpane.getColumnConstraints().addAll(column1, column2, column3);

        RowConstraints row1 = new RowConstraints();
        row1.setFillHeight(true);
        RowConstraints row2 = new RowConstraints();
        row2.setFillHeight(true);
        gridpane.getRowConstraints().addAll(row1, row2);

        // File Name label
        Label label_file = new Label("File Name");
        GridPane.setHalignment(label_file, HPos.RIGHT);
        gridpane.add(label_file, 0, 0);

        // File Name field
        TextField field_file = new TextField();
        field_file.setEditable(false);
        GridPane.setHalignment(field_file, HPos.LEFT);
        gridpane.add(field_file, 1, 0);

        // File Name button
        Button button_file = new Button();
        button_file.setGraphic(new ImageView(icoFile));
        button_file.setOnAction((ActionEvent t) -> {
            FileChooser fileChooser = new FileChooser();
            file = fileChooser.showOpenDialog(primaryStage);
            field_file.setText(file.toString());
            clearMessageDigest();
        });
        gridpane.add(button_file, 2, 0);

        // SHA-256 label
        Label label_sha256 = new Label("SHA-256");
        GridPane.setHalignment(label_sha256, HPos.RIGHT);
        gridpane.add(label_sha256, 0, 1);

        // SHA-256 field
        field_sha256 = new TextField();
        field_sha256.setEditable(false);
        GridPane.setHalignment(field_sha256, HPos.LEFT);
        gridpane.add(field_sha256, 1, 1);

        // SHA-256 button
        Button button_sha256 = new Button();
        button_sha256.setGraphic(new ImageView(icoPen));
        button_sha256.setOnAction((ActionEvent t) -> {
            try {
                String md = calcMessageDigest("SHA-256");
                field_sha256.setText(md);
            } catch (NoSuchAlgorithmException | IOException ex) {
                Logger.getLogger(HashCalc.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
        gridpane.add(button_sha256, 2, 1);

        root.setCenter(gridpane);
        primaryStage.setResizable(false);
        primaryStage.setTitle("HashCalc");
        primaryStage.getIcons().add(icoApp);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    void clearMessageDigest() {
        field_sha256.setText("");
    }

    String calcMessageDigest(String algorithm) throws NoSuchAlgorithmException, FileNotFoundException, IOException {

        if (isEmpty(file)) {
            return "";
        }
        if (!checkBeforeReadfile(file)) {
            return "";
        }

        MessageDigest md = MessageDigest.getInstance(algorithm);
        FileInputStream in = new FileInputStream(file);

        byte[] dataBytes = new byte[1024];

        int nread = 0;
        while ((nread = in.read(dataBytes)) != -1) {
            md.update(dataBytes, 0, nread);
        }
        byte[] mdbytes = md.digest();

        return DatatypeConverter.printHexBinary(mdbytes);
    }

    boolean isEmpty(File value) {
        return value == null || value.length() == 0;
    }

    static boolean checkBeforeReadfile(File read) {
        if (read.exists()) {
            if (read.isFile() && read.canRead()) {
                return true;
            }
        }

        return false;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

実行例

試しに、Fedora 23 の Live-CD のイメージを使ってみましたが、まあ許容できる時間で結果を返してくれます。本格的なユーティリティプログラムとして使うには、もう少し GUI を作りこむ必要がありそうです。

参考サイト

  1. Java SHA Hashing Example
  2. bitwalk123/HashCalc

 

0 件のコメント: