0
0

【Java初心者】Google Tinkを使った電子署名

Last updated at Posted at 2024-02-18

電子署名とは

Wikipediaには

電子署名とは、電磁的記録に付与する、電子的な徴証であり、
紙文書における印章やサインに相当する役割をはたすものである。
主に本人確認や、改竄検出符号と組み合わせて偽造・改竄の防止のために用いられる。 
電子署名を実現する仕組みとしては、公開鍵暗号方式に基づくデジタル署名が有力である。

とあります。

自分の秘密鍵でファイルに署名し、それを予め配布しておいた公開鍵で検証することで、送信者が「正しい人」であることがわかります。

Javaで書いてみました

Tinkは、バージョンアップのたびに、APIが変わり、以前書いたコードが非推奨となることが多いため、その都度ドキュメントを見ながら修正しています。

以下に示すコードはtink-1.12.0.jarを用いています。依存ライブラリーとして protobuf-java と gson が必要です。

package sample2024;

import com.google.crypto.tink.CleartextKeysetHandle;
import com.google.crypto.tink.InsecureSecretKeyAccess;
import com.google.crypto.tink.JsonKeysetReader;
import com.google.crypto.tink.KeyTemplates;
import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.PublicKeySign;
import com.google.crypto.tink.PublicKeyVerify;
import com.google.crypto.tink.TinkJsonProtoKeysetFormat;
import com.google.crypto.tink.signature.SignatureConfig;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.Base64;

public class SignatureTest {

    public static void main(String[] args) {
        try {
            String plainText = "こんにちは"; // 署名したいテキスト
            System.out.println("署名したいテキスト:" + plainText);
            SignatureConfig.register();
            System.out.println("電子署名秘密鍵を生成");
            KeysetHandle privateKeysetHandle
                    = KeysetHandle.generateNew(KeyTemplates.get("ECDSA_P256"));

            // 秘密鍵をファイルに保存する場合(セキュリティー上推奨されていません)
            // String SignaturePrivKey = "signature_priv.key";
            // Path sigPrivFile = Paths.get(SignaturePrivKey);
            // System.out.println("Hybrid秘密鍵を保存");
            // String serializedmacKeyset = TinkJsonProtoKeysetFormat.serializeKeyset(
            //        privateKeysetHandle, InsecureSecretKeyAccess.get());
            // Files.write(sigPrivFile, serializedmacKeyset.getBytes(UTF_8));
            // 秘密鍵をファイルから読み込む(セキュリティー上推奨されていません)
            // serializedmacKeyset = Files.readString(sigPrivFile, UTF_8);
            // 読み取ったテキストから鍵を抽出する
            //KeysetHandle keysetHandle2 = CleartextKeysetHandle.read(
            //        JsonKeysetReader.withString(serializedmacKeyset));
            // 秘密鍵から公開鍵を作成
            KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle();
            System.out.println("電子署名公開鍵(相手に渡すもの):" + toJson(publicKeysetHandle));

            // 電子署名をするためには秘密鍵と もとのテキストが必要
            PublicKeySign signer = privateKeysetHandle.getPrimitive(PublicKeySign.class);
            byte[] signature = signer.sign(plainText.getBytes());
            String sign_data = new String(Base64.getEncoder().encode(signature));
            System.out.println("電子署名:" + sign_data);

            PublicKeyVerify verifier = publicKeysetHandle.getPrimitive(PublicKeyVerify.class);
            // 署名を検証するためには電子署名と もとのテキストが必要
            verifier.verify(signature, plainText.getBytes());
            System.out.println("電子署名が検証されました");

        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    private static String toJson(KeysetHandle key) throws GeneralSecurityException {
        return TinkJsonProtoKeysetFormat.serializeKeyset(key, InsecureSecretKeyAccess.get());
    }
}

実行結果

署名したいテキスト:こんにちは
電子署名秘密鍵を生成
電子署名公開鍵(相手に渡すもの):{"primaryKeyId":3084469744,"key":[{"keyData":{"typeUrl":"type.googleapis.com/google.crypto.tink.EcdsaPublicKey","value":"EgYIAxACGAIaIQDS8szXsh4hV1Rxp5XFfA5CP3wbPvGgChsIsPTEkfkpxCIhAK5aeSDBZNKvHH4PYZNIuee5gykLtDk6AQQPgvKWrBzt","keyMaterialType":"ASYMMETRIC_PUBLIC"},"status":"ENABLED","keyId":3084469744,"outputPrefixType":"TINK"}]}

電子署名:AbfZRfAwRgIhAJcqUHB/JlzDrPsJyFkqizlLCCnbG8CqkdX7ECUb9YWaAiEA11bfaG1Dn9Uvw0gV3ILZhZ3zIKYMyYPwhOo6UfZ6YBU=
電子署名が検証されました
0
0
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
0
0