Coverage Summary for Class: Secp256k1Service (org.ethereum.crypto.signature)

Class Class, % Method, % Line, %
Secp256k1Service 100% (1/1) 100% (2/2) 66.7% (10/15)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2020 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.crypto.signature; 21  22 import org.ethereum.crypto.ECKey; 23  24 import javax.annotation.Nullable; 25 import java.security.SignatureException; 26  27 /** 28  * Service in charge of the implementations of all the Signature related functionality. 29  * Functions: 30  * - Sign data (future) 31  * - Recover PK from signature 32  * - Verify 33  */ 34 public interface Secp256k1Service { 35  36  37  /** 38  * Given a piece of text and a message signature encoded in base64, returns an ECKey 39  * containing the public key that was used to sign it. This can then be compared to the expected public key to 40  * determine if the signature was correct. 41  * 42  * signature.v => from 31 to 34 is compressed 43  * => from 27 to 30 is uncompressed 44  * 45  * @param messageHash a piece of human readable text that was signed 46  * @param signature The message signature 47  * @return - 48  * @throws SignatureException If the public key could not be recovered or if there was a signature format error. 49  */ 50  default ECKey signatureToKey(byte[] messageHash, ECDSASignature signature) throws SignatureException { 51  int header = signature.getV() & 0xFF; 52  // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, 53  // 0x1D = second key with even y, 0x1E = second key with odd y 54  if (header < 27 || header > 34) { 55  throw new SignatureException("Header byte out of range: " + header); 56  } 57  58  boolean compressed = false; 59  if (header >= 31) { 60  compressed = true; 61  header -= 4; 62  } 63  int recId = header - 27; 64  ECKey key = this.recoverFromSignature(recId, signature, messageHash, compressed); 65  if (key == null) { 66  throw new SignatureException("Could not recover public key from signature"); 67  } 68  return key; 69  } 70  /** 71  * <p>Given the components of a signature and a selector value, recover and return the public key 72  * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p> 73  * 74  * <p>The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the correct one. Because 75  * the key recovery operation yields multiple potential keys, the correct key must either be stored alongside the 76  * signature, or you must be willing to try each recId in turn until you find one that outputs the key you are 77  * expecting.</p> 78  * 79  * <p>If this method returns null it means recovery was not possible and recId should be iterated.</p> 80  * 81  * <p>Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, and if the 82  * output is null OR a key that is not the one you expect, you try again with the next recId.</p> 83  * 84  * @param recId Which possible key to recover. 85  * @param sig the R and S components of the signature, wrapped. 86  * @param messageHash Hash of the data that was signed. 87  * @param compressed Whether or not the original pubkey was compressed. 88  * @return An ECKey containing only the public part, or null if recovery wasn't possible. 89  */ 90  @Nullable 91  ECKey recoverFromSignature(int recId, ECDSASignature sig, byte[] messageHash, boolean compressed); 92  93  /** 94  * <p>Verifies the given ECDSA signature against the message bytes using the public key bytes.</p> 95  * 96  * <p>When using native ECDSA verification, data must be 32 bytes, and no element may be 97  * larger than 520 bytes.</p> 98  * 99  * @param data Hash of the data to verify. 100  * @param signature signature. 101  * @param pub The public key bytes to use. 102  * @return - 103  */ 104  boolean verify(byte[] data, ECDSASignature signature, byte[] pub); 105  106  /** 107  * Utility method to check params. 108  * 109  * @param test 110  * @param message 111  */ 112  default void check(boolean test, String message) { 113  if (!test) { 114  throw new IllegalArgumentException(message); 115  } 116  } 117  118 }