I created a simple UserInterface that allows a user to send a transaction, similar to bitcoin. Among other things, the user must enter his private key (this is already encoded!). However, I have difficulties to create a signature from it. My private Key is decoded like this: SHA3Helper.digestToHex( ( ( BCECPrivateKey ) keyPair.getPrivate( ) ).getD( ).toByteArray( ) ) ); SHA3Helper is just to convert a byteArray to a String and acutally not very important here. I also use the secp256k1 elliptic curve. Here is the method I use to create the signature:
public static byte[] GenerateSignature(String transaction, byte[] keyPriv) throws Exception {
Security.addProvider(new BouncyCastleProvider());
byte[] privateKeyBytes = keyPriv;
KeyFactory kf = KeyFactory.getInstance("ECDSA");
PrivateKey pKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
Signature ecdsaSign = Signature.getInstance("ECDSA", "BC");
ecdsaSign.initSign(pKey);
ecdsaSign.update(transaction.getBytes("UTF-8"));
byte[] signature = ecdsaSign.sign();
System.out.println(signature.toString());
return signature;
}
Heres the simple method for reading the users input
@FXML
void submitPressed(ActionEvent event) {
System.out.println("Submit Pressed");
byte[] sender = SHA3Helper.hexToDigest(senderField.getText());
byte[] receiver = SHA3Helper.hexToDigest(receiverField.getText());
double amount = Double.parseDouble(amountField.getText());
double tfbp = Double.parseDouble(tfbpField.getText());
double tfl = Double.parseDouble(tflField.getText());
byte[] privateKey = SHA3Helper.hexToDigest(keyField.getText());
Transaction transaction = new Transaction(sender, receiver, amount, 0, tfbp, tfl);
System.out.println(transaction.getAmount());
try {
byte[] signature = SignatureHelper.GenerateSignature(transaction.asJSONString(), privateKey);
transaction.setSignature(signature);
System.out.println("Signatur: " transaction.getSignature());
} catch (Exception e) {
e.printStackTrace();
}
DependencyManager.getPendingTransactions().addPendingTransaction(transaction);
}
As you can see, I convert the privateKey string directly into a byte array and pass this to my generateSignature method.
Full Stack Trace:
java.security.spec.InvalidKeySpecException: encoded key spec not recognized: failed to construct sequence from byte[]: DEF length 112 object truncated by 82
at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePrivate(Unknown Source)
at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePrivate(Unknown Source)
at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:389)
at main.utils.SignatureHelper.GenerateSignature(SignatureHelper.java:65)
at main.Controller.submitPressed(Controller.java:50)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8923)
at javafx.scene.control.Button.fire(Button.java:203)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3894)
at javafx.scene.Scene.processMouseEvent(Scene.java:1887)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)
It seems the error is probably in the conversion but I can't find it.
CodePudding user response:
Try this to reproduce the privateKey from the decodedBytes:
public static PrivateKey getPrivateKeyFromBytes( byte[] privateKey ){
PrivateKey result;
try
{
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec( CURVE_NAME );
KeyFactory kf = KeyFactory.getInstance( ALGORITHM, PROVIDER );
ECNamedCurveSpec params =
new ECNamedCurveSpec( CURVE_NAME, spec.getCurve( ), spec.getG( ), spec.getN( ) );
BigInteger s = new BigInteger(1, privateKey);
ECPrivateKeySpec pubKeySpec = new ECPrivateKeySpec(s, params);
result = kf.generatePrivate( pubKeySpec );
}
catch ( Exception e )
{
result = null;
}
return result;
}