3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jsSHAとjava.security.MessageDigestを試してみる

Posted at

はじめに

jsSHAとjava.security.MessageDigestを使ってSHA-256を試してみます。

jsSHAにデモがあります。まず、このデモを使って、SHA-256の値を用意します。この記事では、入力テキストをtokyo、入力タイプをTEXT、SHAバージョンをSHA-256、出力タイプをBase64とします。もちろん、他のケースで試すこともできます。

出力ハッシュ値はr+BFeQBASczOGEOkC9+euF86SDk5A3XjXQAYp/mqcMg=です。

スクリーンショット 2015-08-17 21.36.50.png

java.security.MessageDigestのほうはScalaでSHA-256の値を用意します。

この記事では、jsSHAとjava.security.MessageDigestのSHA-256の値を確認して、気を付けることなどを紹介します。

準備

Base64を使うために、下記のようなbuild.sbtを用意します。

build.sbt
libraryDependencies += "commons-codec" % "commons-codec" % "1.10"

REPL起動のためのコマンドラインは、$ sbt consoleです。

Javaのバージョンが古い場合、java.security.MessageDigestが使えないかもしれません。Javaのバージョンは1.8を使いました。

REPL

REPLで試してみましたが、シンタックスハイライトが効かないこともあり、読み難いです。

Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.security.MessageDigest
import java.security.MessageDigest

scala> MessageDigest.getInstance("SHA-256")
res0: java.security.MessageDigest =
SHA-256 Message Digest from SUN, <initialized>


scala> res0.digest
                                         def digest(): Array[Byte]                def digest(Array[Byte]): Array[Byte]     def digest(Array[Byte], Int, Int): Int

scala> res0.digest("tokyo".getBytes)
res1: Array[Byte] = Array(-81, -32, 69, 121, 0, 64, 73, -52, -50, 24, 67, -92, 11, -33, -98, -72, 95, 58, 72, 57, 57, 3, 117, -29, 93, 0, 24, -89, -7, -86, 112, -56)

scala> import org.apache.commons.codec.binary.Base64
import org.apache.commons.codec.binary.Base64

scala> Base64.encodeBase64(res1)
res2: Array[Byte] = Array(114, 43, 66, 70, 101, 81, 66, 65, 83, 99, 122, 79, 71, 69, 79, 107, 67, 57, 43, 101, 117, 70, 56, 54, 83, 68, 107, 53, 65, 51, 88, 106, 88, 81, 65, 89, 112, 47, 109, 113, 99, 77, 103, 61)

scala> Base64.encodeBase64String(res1)
res3: String = r+BFeQBASczOGEOkC9+euF86SDk5A3XjXQAYp/mqcMg=

scala> Base64.encodeBase64URLSafeString(res1)
res4: String = r-BFeQBASczOGEOkC9-euF86SDk5A3XjXQAYp_mqcMg

scala> Base64.encodeBase64ChunkedString(res1)
<console>:12: error: value encodeBase64ChunkedString is not a member of object org.apache.commons.codec.binary.Base64
              Base64.encodeBase64ChunkedString(res1)
                     ^

scala> Base64.encodeBase64Chunked(res1)
res6: Array[Byte] = Array(114, 43, 66, 70, 101, 81, 66, 65, 83, 99, 122, 79, 71, 69, 79, 107, 67, 57, 43, 101, 117, 70, 56, 54, 83, 68, 107, 53, 65, 51, 88, 106, 88, 81, 65, 89, 112, 47, 109, 113, 99, 77, 103, 61, 13, 10)

scala> new String(Base64.encodeBase64Chunked(res1))
res7: String =
"r+BFeQBASczOGEOkC9+euF86SDk5A3XjXQAYp/mqcMg=
"

scala> Base64.decodeBase64(res3.getBytes)
res8: Array[Byte] = Array(-81, -32, 69, 121, 0, 64, 73, -52, -50, 24, 67, -92, 11, -33, -98, -72, 95, 58, 72, 57, 57, 3, 117, -29, 93, 0, 24, -89, -7, -86, 112, -56)

scala> new String(res8)
res9: String = ��Ey?@I��?C�
                           ߞ�_:H99?u�]??���p�

scala> Base64.decodeBase64(res4.getBytes)
res10: Array[Byte] = Array(-81, -32, 69, 121, 0, 64, 73, -52, -50, 24, 67, -92, 11, -33, -98, -72, 95, 58, 72, 57, 57, 3, 117, -29, 93, 0, 24, -89, -7, -86, 112, -56)

scala> new String(res10)
res11: String = ��Ey?@I��?C�
                            ߞ�_:H99?u�]??���p�

scala> Base64.decodeBase64(res6)
res12: Array[Byte] = Array(-81, -32, 69, 121, 0, 64, 73, -52, -50, 24, 67, -92, 11, -33, -98, -72, 95, 58, 72, 57, 57, 3, 117, -29, 93, 0, 24, -89, -7, -86, 112, -56)

scala> new String(res12)
res13: String = ��Ey?@I��?C�
                            ߞ�_:H99?u�]??���p�

scala>

コードも用意してみます。実行するためのコマンドラインは$ sbt runです。

object Main extends App {
  import java.security.MessageDigest
  val hash = MessageDigest.getInstance("SHA-256").digest("tokyo".getBytes)

  println("------------------------------")
  println(hash)

  import org.apache.commons.codec.binary.Base64

  println("------------------------------")
  val base = Base64.encodeBase64(hash)
  println(new String(base))
  //=> r+BFeQBASczOGEOkC9+euF86SDk5A3XjXQAYp/mqcMg=

  println("------------------------------")
  val baseSafe = Base64.encodeBase64URLSafe(hash)
  println(new String(baseSafe))
  //=> r-BFeQBASczOGEOkC9-euF86SDk5A3XjXQAYp_mqcMg

  println("------------------------------")
  val baseChunked = Base64.encodeBase64Chunked(hash)
  println(new String(baseChunked))
  //=> "r+BFeQBASczOGEOkC9+euF86SDk5A3XjXQAYp/mqcMg=
  //   "

  println("------------------------------")
  println(Base64.decodeBase64(base) sameElements hash)
  //=> true

  println("------------------------------")
  println(Base64.decodeBase64(baseSafe) sameElements hash)
  //=> true

  println("------------------------------")
  println(Base64.decodeBase64(baseChunked) sameElements hash)
  //=> true

}

まず、ハッシュ値を生成しています。hashがハッシュ値です。

次に、そのハッシュ値をBase64でエンコードして、String型のオブジェクトを生成しています。エンコードのためのメソッドはいくつかありますが、ここではencodeBase64encodeBase64URLSafeencodeBase64Chunkedを使っています。デコードのためのメソッドはdecodeBase64です。

さて、エンコードは複数あります。どのエンコードで生成した値がjsSHAで生成した値と同じ値になるのでしょうか?目を細めて確認してみますと、encodeBase64で生成した値がjsSHAで生成した値と同じ値になるようです。ほかのエンコードで生成した値は少し違う値になるようです。

余談ですが、配列(Array)の比較は==ではなく、sameElementsを使います。

scala> Seq() == Seq(1)
res0: Boolean = false

scala> Seq() == Seq()
res1: Boolean = true

scala> Vector() == Vector(1)
res2: Boolean = false

scala> Vector() == Vector()
res3: Boolean = true

scala> Array() == Array(1)
res4: Boolean = false

scala> Array() == Array()
res5: Boolean = false

scala> Array() sameElements Array(1)
res6: Boolean = false

scala> Array() sameElements Array()
<console>:8: error: polymorphic expression cannot be instantiated to expected type;
 found   : [T]Array[T]
 required: scala.collection.GenIterable[?]
              Array() sameElements Array()
                                        ^

scala> Array(1) sameElements Array(1)
res8: Boolean = true

scala>

SeqまたはVectorでは==で比較することができますが、Arrayでは==で比較すると問答無用でfalseになります。

まとめ

話が長くなりましたが、気を付けることは用途に合わせてエンコードを選択することとArrayの比較では==ではなくsameElementsを使うことです。

参考URL

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?