SHA! えびばーでぃ!
こんばんちょ。
さっきふと、自分のtwitterIDで検索かけたら
どんな検索結果が出てくるのかな?と思い、
ぐぐってみました。
青春フルパワーで、うっきゅ~!!!!!!!
二年前も頭の悪さは相変わらずでした。
ところで先週、文字列をハッシュ関数化するメソッドとか、
エンコード(暗号化)するメソッドを作ったよ。(唐突)
具体的には
・SHA-1するメソッド
・HmacSHA-256するメソッド
・Base64エンコードするメソッド
このみっつ。(「SHA-?する」って表現でいいのかな)
今日はこの3つのメソッドについて、
またそれに関連する各用語について少しまとめたいと思うよ。
それでは。
・SHAとは
Secure Hash Algorithm(セキュアハッシュアルゴリズム)のこと。
一群の関連したハッシュ関数であり、
アメリカ国立標準技術研究所 (NIST) によって
アメリカ政府標準のハッシュ関数として採用されている。(Wiki引用)
現在、SHAは
「SHA-0」「SHA-1」「SHA-2」「SHA-3」の4種類が存在している。
通信する時のセキュリティを強化するために、
通信したい情報をぱっと見で分からない形に変える方法の一つがSHAって認識~
(恒例:うまくまとまらない)
では次に。
・SHA-1とは
認証やデジタル署名などに使われるハッシュ関数のひとつ。
2の64乗ビット以下の原文から160ビットの「ハッシュ値」を生成し、
通信経路の両端で比較することで、
通信途中で原文が改ざんされていないかを検出することができる。
SHA-1はもっともよく使われる関数であり、
さまざまなセキュリティのアプリケーションやプロトコルに採用されている。
計算方法には初期値敏感性の不可逆な一方向関数を含むため、
ハッシュ値は擬似的な乱数のような値をとり、
これをもとに原文を再現することはできない。
(引用元:http://e-words.jp/w/SHA-1.html)
・SHA-2とは
任意長の原文から固定長の特徴的な値である
「ハッシュ値」を求める計算手順(アルゴリズム)の標準規格の一つ。
「SHA-224」「SHA-256」「SHA-384」「SHA-512」
の4つをまとめた総称。
末尾の数字がそれぞれのハッシュ値のビット長を表しており、
一般的にはSHA-256が最もよく利用されている。
(引用元:http://e-words.jp/w/SHA-2.html)
ハッシュ関数の種類だね~
用途に応じてどのハッシュ関数に変換するか決めるみたい。
ちなみに
いちばんセキュリティ安全性が高いのはSHA-512。
ハッシュ関数化のパターンとしては
2の512乗 通りのハッシュ値をとるんだって。
約1.341×10の154乗…
154乗ってなんぞや。
用語の説明はこんなもんにして、
メソッドお披露目~じゃーん。まずはSHA-1化メソッドから。
/** * SHA1化する * * @param str * @return SHA1化した文字列 */ public static String toSHA1(String str) { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } byte[] sha1; try { sha1 = digest.digest(str.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } return new String(Hex.encodeHex(sha1)); }
してますね~SHA-1。
最後に文字列を16進数化 Hex.encodeHex(sha1)してるのは、
ハッシュキーの長さが16進数で表されてるから?
なんで16進数化するんですかって聞いた気がするけど
忘れてもーた。モーゼの墓。(?)
あした確認しよ。
つぎにSHA-256化メソッド。
/** * SHA256化する * * @param str * @return SHA256化した文字列 */ public static String toSHA256(String str) { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } byte[] sha256; try { sha256 = digest.digest(str.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } return new String(Hex.encodeHex(sha256)); }
はい、何が変わったって
MessageDigest.getInstance("SHA-1")の部分が
MessageDigest.getInstance("SHA-256")に変わっただけだよ。
ふっつーーにSHA-?化するのは簡単っていうか
結構色々なサイトに方法(ソース)が乗っかってるから、
それを参考にすればいいんだけど、
今回のミッション、実は
「指定された公開鍵を使ってSHA-256化するんやで」だったんですよ。
これがなかなかネット上に方法が乗っかってなくて
ミッションコンプリーツに苦労しました。
しかも結局先輩が参考になりそうなサイトを見つけてくれて、
それを見ながらコードを書いたっていう。
じまさんダメダメじゃないっすか。
ダメダメじまさんですよ。
そんな感じで完成したSHA-256化メソッドfeat.公開鍵がこちら。
/** * HmacSHA256化する * * @param target 暗号化したい文字列 * @param key 公開鍵 * @return HmacSHA256エンコード化した文字列 */ public static String toHmacSHA256(String target, String key) { byte[] result; try { SecretKeySpec sk = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(sk); result = mac.doFinal(target.getBytes("UTF-8")); } catch (Exception e) { throw new RuntimeException(); } return new String(Hex.encodeHex(result)); }
HmacSHA256って誰だおまえーーー
って感じだけど、とにかく公開鍵を使って暗号化するときは
java.security.MessageDigestじゃなくて、
javax.crypto.Macっていうのを使うんだって。
new SecretKeySpecすることで、
ただの文字列として渡ってきた鍵を、「公開鍵」として
使える状態に復元するところから始めなきゃいけないんだって。
で、Macさんにnew SecretKeySpecした公開鍵を渡してあげて、
doFinalでSHA-256化してもらう。的な流れ。
ヒェーーーうまくまとまらない。
そういえば、公開鍵ってそもそもなんだよ!唐突に出てきたな!
って感じなので、さらっと公開鍵についても触れる。
・公開鍵暗号とは
対になる2つの鍵を使ってデータの暗号化・復号を行う暗号方式。
公開鍵暗号では暗号化に使う鍵と復号に使う鍵が分離されており、
公開鍵で暗号化されたデータは秘密鍵でしか復号することができない。
鍵の持ち主は復号に使う鍵のみを他人に知られないように管理し、
暗号化に使う鍵は公開する。
このため、暗号化に使う鍵は公開鍵、復号に使う鍵は秘密鍵と呼ばれる。
(引用元:http://e-words.jp/w/E585ACE9968BE98DB5E69A97E58FB7.html)
これまたセキュリティ強度を上げる方法の一つですな。
最後にもういっちょ、セキュリティ強化の仕上げに
Base64エンコーディングもかけますか。
/** * Base64エンコードする * * @param sha256 * @return Base64エンコード化した文字列 */ public static String toBase64(String sha256) { byte[] encodedBytes; String result; try { encodedBytes = Base64.encodeBase64(sha256.getBytes("UTF-8")); result = new String(encodedBytes, "UTF-8"); } catch (UnsupportedEncodingException e) { // 通常ありえない throw new RuntimeException(); } return result; }
もうづかれだ。ねむい。
最後に。importしたのはこのひとたち。
本番環境では上のメソッドたちは一つのクラスにまとまってるよ。
import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex;
あとあれ。現場では、
Sha256化した文字列をさらにBase64エンコーディングしていたよ。
…なんかまた微妙な記事を投稿してしまった。
三連休終わってしまった。
明日からもがんばるどおおおおおおおドドドド
なにするんだろ。
おやスヤァ。