This article belongs to H Verify external signature in Tink and is part 1.
Lets start the mission with a small program that generates a Private Key and Public Key keypair with ECDSA-keys and uses the JCE for this task.
As Tink can work with 3 key sizes or curves („Nist P256“ = 256 Bit, „Nist P384“ = 384 Bit and „Nist P521“ = 521 Bit) the solution generates 3 files named „ecdsa_classic_data_xxx.txt“, where xxx ist the used key size.
Please be aware that the material for the signature is hashed with „SHA256withECDSA“ for the key length „256“. When using the other key lengths „384“ and „521“ the hashroutine is „SHA512withECDSA“.
The Public Key gets encoded to a byte array and saved in a Base64-coded string. The second line in the datafile contains the message byte array in a Base64-coded string. The third line is the generated signature as byte array in a Base64-coded string.
All files are saved on the classpath.
Here is the sourcecode:
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 |
package tinkExternalSignatureVerification; /* * Herkunft/Origin: http://javacrypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: frei verwendbares Programm (Public Domain) * Copyright: This is free and unencumbered software released into the public domain. * Lizenttext/Licence: <http://unlicense.org> * getestet mit/tested with: Java Runtime Environment 8 Update 191 x64 * getestet mit/tested with: Java Runtime Environment 11.0.1 x64 * Datum/Date (dd.mm.jjjj): 18.11.2019 * Funktion: erzeugt eine ecdsa-signatur mittels jce * Function: generates an ecdsa-signature with jce * * Sicherheitshinweis/Security notice * Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine korrekte Funktion, * insbesondere mit Blick auf die Sicherheit ! * Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird. * The program routines just show the function but please be aware of the security part - * check yourself before using in the real world ! * */ import java.io.FileWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.util.Base64; public class GenerateEcdsaClassicSignature { public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException { System.out.println("Generate a ECDSA Private-/PublicKey and signs a message"); byte[] message = "This is the message".getBytes("utf-8"); String messageString = ""; String filenameTemplate = "ecdsa_classic_data_"; String filename; byte[] signature = null; String signatureString = ""; PrivateKey privKey; PublicKey pubKey; String pubKeyString = ""; int[] keylength = new int[] { 256, 384, 521 }; // iterate through keylength for (int myKeylength : keylength) { filename = filenameTemplate + String.valueOf(myKeylength) + ".txt"; // generate keypair KeyPair keyPair = generateEcdsaClassicKeyPair(myKeylength); privKey = keyPair.getPrivate(); pubKey = keyPair.getPublic(); signature = null; // sign the message switch (myKeylength) { case 256: { signature = signEcdsaClassic(privKey, message, "SHA256withECDSA"); break; } case 384: { signature = signEcdsaClassic(privKey, message, "SHA512withECDSA"); break; } case 521: { signature = signEcdsaClassic(privKey, message, "SHA512withECDSA"); break; } default: { System.out.println("Error - signature keylength not supported"); System.exit(0); } } // convert data to base64 pubKeyString = Base64.getEncoder().encodeToString(pubKey.getEncoded()); messageString = Base64.getEncoder().encodeToString(message); signatureString = Base64.getEncoder().encodeToString(signature); // save data to file writeData(filename, pubKeyString, messageString, signatureString); System.out.println("Data written to:" + filename); } } public static KeyPair generateEcdsaClassicKeyPair(int keylengthInt) throws NoSuchAlgorithmException, NoSuchProviderException { KeyPairGenerator keypairGenerator = KeyPairGenerator.getInstance("EC"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); keypairGenerator.initialize(keylengthInt, random); return keypairGenerator.generateKeyPair(); } public static byte[] signEcdsaClassic(PrivateKey privateKey, byte[] message, String ecdsaHashtype) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException { Signature signature = Signature.getInstance(ecdsaHashtype); signature.initSign(privateKey); signature.update(message); byte[] sigByte = signature.sign(); return sigByte; } public static void writeData(String filenameWrite, String pubKeyWrite, String messageWrite, String signatureWrite) throws IOException { FileWriter fw = new FileWriter(filenameWrite); fw.write(pubKeyWrite + "\n"); fw.write(messageWrite + "\n"); fw.write(signatureWrite + "\n"); fw.write( "This file contains data in base64-format: publicKey, message, signature. Number in filename is keylength."); fw.flush(); fw.close(); } } |
The console output is very short:
1 2 3 4 |
Generate a ECDSA Private-/PublicKey and signs a message Data written to:ecdsa_classic_data_256.txt Data written to:ecdsa_classic_data_384.txt Data written to:ecdsa_classic_data_521.txt |
All sourcecodes to this solution are available in my Github-Archive with this link: https://github.com/java-crypto/H-Google-Tink. All programs run with Java 8 and Java 11.
The licence (or better unlicence) to my solution is available here: Lizenz-Seite.
Last edit: 18.11.2019