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 にイメージを含む全ソースをアップしてあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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 を作りこむ必要がありそうです。
参考サイト