{"id":16427,"date":"2021-03-02T00:14:41","date_gmt":"2021-03-01T23:14:41","guid":{"rendered":"http:\/\/blog.wenzlaff.de\/?p=16427"},"modified":"2022-04-20T14:26:49","modified_gmt":"2022-04-20T12:26:49","slug":"ecc","status":"publish","type":"post","link":"http:\/\/blog.wenzlaff.de\/?p=16427","title":{"rendered":"Signieren von Nachrichten mit Digital Signature Algorithm (ECDSA) in Java und Elliptische-Kurven-Kryptografie (ECC) secp256k1"},"content":{"rendered":"<p>Wie werden in Java Nachrichten signiert und vom Empf\u00e4nger validiert? Das geht mit ein paar Zeile aus dem Java Package java.security. Wir verwenden die auch in Bitcoin verwendeten Elliptische-Kurven-Kryptografie  <strong>secp256k1<\/strong>. Was wollen wir zu Entspannung nach Feierabend machen? <\/p>\n<p>Das wird in diesem BPMN-Diagramm dargestellt:<\/p>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/03\/wenzlaff.de-2021-03-01-um-20.14.29.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/03\/wenzlaff.de-2021-03-01-um-20.14.29.png\" alt=\"\" width=\"2430\" height=\"524\" class=\"aligncenter size-full wp-image-16428\" \/><\/a><\/p>\n<p>Hier die kommentierte Java Klasse: &#8230;<!--more--><\/p>\n<pre class=\"lang:java decode:true \" >\r\n\r\n\r\npackage de.wenzlaff.twhash;\r\n\r\nimport java.security.Key;\r\nimport java.security.KeyFactory;\r\nimport java.security.KeyPair;\r\nimport java.security.KeyPairGenerator;\r\nimport java.security.PrivateKey;\r\nimport java.security.PublicKey;\r\nimport java.security.SecureRandom;\r\nimport java.security.Signature;\r\nimport java.security.spec.ECGenParameterSpec;\r\nimport java.security.spec.EncodedKeySpec;\r\nimport java.security.spec.X509EncodedKeySpec;\r\nimport java.util.Base64;\r\n\r\n\/**\r\n * ECDSA Beispiel in vier Schritten mit dem java.security Package.\r\n * \r\n * Es muss ja nicht immer ein andere Lib sein.\r\n * \r\n * @author Thomas Wenzlaff\r\n *\/\r\npublic class ECCSignatur {\r\n\r\n\tpublic ECCSignatur() throws Exception {\r\n\r\n\t\t\/\/ 1. Generieren des public\/private Key mit Digital Signature Algorithm (ECDSA)\r\n\t\t\/\/ die Keys k\u00f6nnen wiederverwendet werden\r\n\t\tSystem.out.println(\"Keys erzeugen\");\r\n\t\tECGenParameterSpec ecSpec = new ECGenParameterSpec(\"secp256k1\");\r\n\t\tKeyPairGenerator g = KeyPairGenerator.getInstance(\"EC\");\r\n\t\tg.initialize(ecSpec, new SecureRandom(\"Optional mit Seed\".getBytes()));\r\n\t\tKeyPair keypair = g.generateKeyPair();\r\n\r\n\t\tPublicKey publicKey = keypair.getPublic();\r\n\t\tviewKey(\"Public\", publicKey);\r\n\r\n\t\tPrivateKey privateKey = keypair.getPrivate();\r\n\t\tviewKey(\"Privater\", privateKey);\r\n\r\n\t\t\/\/ wir versenden diese Testnachricht:\r\n\r\n\t\tString nachricht = \"Das ist toll mit den Signaturen und Digital Signature Algorithm (ECDSA)!\";\r\n\r\n\t\t\/\/ 2. Signieren der Nachricht mit privaten Key\r\n\t\tSystem.out.println(\"Signieren\");\r\n\t\tSignature ecdsaSign = Signature.getInstance(\"SHA256withECDSA\");\r\n\t\tecdsaSign.initSign(privateKey);\r\n\t\tecdsaSign.update(nachricht.getBytes(\"UTF-8\"));\r\n\r\n\t\tbyte[] signature = ecdsaSign.sign();\r\n\t\tString publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());\r\n\t\tString signaturBase64 = Base64.getEncoder().encodeToString(signature);\r\n\r\n\t\t\/\/ 3. \u00dcbermitteln der Nachricht den Public Key und die Signatur der Nachricht an\r\n\t\t\/\/ den Empf\u00e4nger\r\n\t\tSystem.out.println(\"-------------- das wird an den Empf\u00e4nger \u00fcbertragen -------------\");\r\n\t\tSystem.out.println(\"Die Nachricht die signiert wurde: \" + nachricht);\r\n\t\tSystem.out.println(\"Der Public Key in Base64 Format: \" + publicKeyBase64);\r\n\t\tSystem.out.println(\"Die Signatur der Nachricht im Base64 Format: \" + signaturBase64);\r\n\r\n\t\t\/\/ 4. Der Empf\u00e4nger \u00fcberpr\u00fcft die Nachricht mit dem Public Key und der Signatur\r\n\r\n\t\tSystem.out.println(\"-------------- das l\u00e4uft beim Empf\u00e4nger -------------\");\r\n\t\tempfaenger(nachricht, publicKeyBase64, signaturBase64);\r\n\t}\r\n\r\n\tprivate void empfaenger(String nachricht, String publicKeyBase64, String signaturBase64) throws Exception {\r\n\r\n\t\tEncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64));\r\n\r\n\t\tKeyFactory keyFactory = KeyFactory.getInstance(\"EC\");\r\n\t\tPublicKey publicKeySender = keyFactory.generatePublic(publicKeySpec);\r\n\r\n\t\tSignature ecdsaVerify = Signature.getInstance(\"SHA256withECDSA\"); \/\/ die gleiche wie der Sender\r\n\t\tecdsaVerify.initVerify(publicKeySender);\r\n\r\n\t\t\/\/ testweise mal einkommentieren um die Nachricht zu ver\u00e4ndern\r\n\t\t\/\/ nachricht = \"HACK!\" + nachricht; \/\/ wurde die Nachricht ver\u00e4ndert, kommt eine\r\n\r\n\t\t\/\/ Fehlermeldung beim verify\r\n\t\tecdsaVerify.update(nachricht.getBytes(\"UTF-8\"));\r\n\r\n\t\t\/\/ das eigentliche \u00fcberpr\u00fcfen und Ergebnis anzeigen\r\n\t\tSystem.out.println(\"Nachricht mit public Key und Signatur \u00fcberpr\u00fcfen. Ergebnis:\");\r\n\t\tboolean result = ecdsaVerify.verify(Base64.getDecoder().decode(signaturBase64));\r\n\t\tif (result) {\r\n\t\t\tSystem.out.println(\"Die \u00fcbertragene Nachricht und die Signatur passen zusammen.\");\r\n\t\t\tSystem.out.println(\"Die Nachricht lautet: \" + nachricht);\r\n\t\t} else {\r\n\t\t\tSystem.err.println(\"Fehler, die Signatur passt nicht zur Nachricht!\");\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void viewKey(String name, Key key) {\r\n\r\n\t\tString encoded = Base64.getEncoder().encodeToString(key.getEncoded());\r\n\t\tSystem.out.println(name + \" Key Base64 Encode: \" + encoded);\r\n\t\tSystem.out.println(name + \" Key: \" + key);\r\n\t\tSystem.out.println(name + \" Key Format: \" + key.getFormat());\r\n\t\tSystem.out.println(name + \" Key Algorithm: \" + key.getAlgorithm());\r\n\t\tSystem.out.println(name + \" Key Encoded: \" + key.getEncoded());\r\n\t}\r\n\r\n\tpublic static void main(String[] args) throws Exception {\r\n\t\tnew ECCSignatur();\r\n\t}\r\n}\r\n<\/pre>\n<p>Das Ergebniss:<\/p>\n<pre class=\"lang:default decode:true \" >Keys erzeugen\r\nPublic Key Base64 Encode: MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMV0xMubTru\/I78sWHYol6Am7hbPGoDhAyPGkkkebh68RlanrTxv6VDEa027wJDYc+f0UrYm70LEgm2wWCMjWCg==\r\nPublic Key: Sun EC public key, 256 bits\r\n  public x coord: 22327985915481677429642520300797029992037926573857920778375831531391096162223\r\n  public y coord: 7953751377618762713704442597204637820923434765570159547797650155666921805322\r\n  parameters: secp256k1 (1.3.132.0.10)\r\nPublic Key Format: X.509\r\nPublic Key Algorithm: EC\r\nPublic Key Encoded: [B@2c7b84de\r\nPrivater Key Base64 Encode: MD4CAQAwEAYHKoZIzj0CAQYFK4EEAAoEJzAlAgEBBCCvqRnRUmavJwZgKY6RBZJmgmjvmC7sNZ19R8ThDVBxhg==\r\nPrivater Key: sun.security.ec.ECPrivateKeyImpl@507\r\nPrivater Key Format: PKCS#8\r\nPrivater Key Algorithm: EC\r\nPrivater Key Encoded: [B@3fee733d\r\nSignieren\r\n-------------- das wird an den Empf\u00e4nger \u00fcbertragen -------------\r\nDie Nachricht die signiert wurde: Das ist toll mit den Signaturen und Digital Signature Algorithm (ECDSA)!\r\nDer Public Key in Base64 Format: MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMV0xMubTru\/I78sWHYol6Am7hbPGoDhAyPGkkkebh68RlanrTxv6VDEa027wJDYc+f0UrYm70LEgm2wWCMjWCg==\r\nDie Signatur der Nachricht im Base64 Format: MEUCIGAngAUASUBOmUHpJDMrTus3HdzRNd98wFJ6vviwUIfTAiEA0dDe8DshzqjrpfDtL5zMFpDqTQMq3KG0NZuOeTk33FQ=\r\n-------------- das l\u00e4uft beim Empf\u00e4nger -------------\r\nNachricht mit public Key und Signatur \u00fcberpr\u00fcfen. Ergebnis:\r\nDie \u00fcbertragene Nachricht und die Signatur passen zusammen.\r\nDie Nachricht lautet: Das ist toll mit den Signaturen und Digital Signature Algorithm (ECDSA)!\r\n<\/pre>\n<p>Wer will kann auch die Nachricht mal ver\u00e4ndern (einkommentieren der HACK Zeile) um den negativen Fall abzubilden.<\/p>\n<p>Die Public Key Ableitung ist eine Einbahnstrassenfunktion, ebenso wie kryptografische Hashfunktionen. Man kann den private Key <strong>nicht<\/strong> aus dem public Key herleiten. Die Sicherheit von digitalen Signaturen h\u00e4ngt wesentlich von dieser Eigenschaft ab. Auch erzeugen mehrere Durchl\u00e4ufe des private Key durch die Ableitungsfunktion stets <strong>denselben public Key<\/strong>.<\/p>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/03\/wenzlaff.de-2021-03-01-um-20.36.11.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2021\/03\/wenzlaff.de-2021-03-01-um-20.36.11.png\" alt=\"\" width=\"2458\" height=\"1188\" class=\"aligncenter size-full wp-image-16431\" \/><\/a><br \/>\nWer mal mit den <strong>Elliptic Curve scalar multiplication<\/strong> spielen will, kann diesen <a href=\"https:\/\/cdn.jsdelivr.net\/gh\/andreacorbellini\/ecc@920b29a\/interactive\/reals-mul.html\" rel=\"noopener\" target=\"_blank\">Online Rechner<\/a> verwenden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wie werden in Java Nachrichten signiert und vom Empf\u00e4nger validiert? Das geht mit ein paar Zeile aus dem Java Package java.security. Wir verwenden die auch in Bitcoin verwendeten Elliptische-Kurven-Kryptografie secp256k1. Was wollen wir zu Entspannung nach Feierabend machen? Das wird in diesem BPMN-Diagramm dargestellt: Hier die kommentierte Java Klasse: &#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[220,4606,5,79,1319],"tags":[4597,1689,4661,4660,4665,4662,4667,2178,4666,1221,4663,2401,4664,449],"class_list":["post-16427","post","type-post","status-publish","format-standard","hentry","category-anleitung","category-crypto","category-java","category-programmierung","category-sicherheit-2","tag-crypto","tag-demo","tag-digital-signature-algorithm","tag-digital-signature-algorithm-ecdsa","tag-ecc","tag-ecdsa","tag-elliptic-curve-scalar-multiplication","tag-java","tag-java-security","tag-package","tag-secp256k1","tag-signatur","tag-signieren","tag-verschluesseln"],"_links":{"self":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/16427","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=16427"}],"version-history":[{"count":0,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/16427\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=16427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=16427"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=16427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}