| 432 | // ==================================================== |
| 433 | |
| 434 | public static Map<String, Object> Ecdsa(Object request, Object secret, Object curve, Object hash) { |
| 435 | String curveName = (curve == null) ? "secp256k1" : toString(curve); |
| 436 | if (!curveName.equals("secp256k1") && !curveName.equals("p256")) { |
| 437 | throw new IllegalArgumentException("Only secp256k1 and p256 are supported"); |
| 438 | } |
| 439 | |
| 440 | if (curveName.equals("p256")) { |
| 441 | // web3j does not support P-256 compact signatures / recovery id (v) |
| 442 | throw new UnsupportedOperationException("web3j-only implementation supports secp256k1 only (p256 not supported)"); |
| 443 | } |
| 444 | |
| 445 | byte[] msg = toBytes(request); |
| 446 | BigInteger privKey = toPrivateKey(secret); |
| 447 | |
| 448 | if (hash != null) { |
| 449 | // msg = (byte[])Hash(msg, hash, "binary"); |
| 450 | // for now assume sha256 check it later |
| 451 | if (!"sha256".equals(hash)) { |
| 452 | throw new IllegalArgumentException("Only sha256 is supported for now"); |
| 453 | } |
| 454 | msg = sha256(msg); |
| 455 | } else { |
| 456 | |
| 457 | // convert msg from hex to binary |
| 458 | msg = hexToBytes(toString(request)); |
| 459 | } |
| 460 | |
| 461 | ECKeyPair keyPair = ECKeyPair.create(privKey); |
| 462 | |
| 463 | Sign.SignatureData sig = Sign.signMessage(msg, keyPair, false); |
| 464 | |
| 465 | int vOut = sig.getV()[0] & 0xFF; |
| 466 | int recoveryV = vOut - 27; |
| 467 | Map<String, Object> out = new HashMap<>(); |
| 468 | out.put("r", Numeric.toHexString(sig.getR()).replaceAll("0x", "") ); |
| 469 | out.put("s", Numeric.toHexString(sig.getS()).replaceAll("0x", "") ); |
| 470 | out.put("v", recoveryV); |
| 471 | return out; |
| 472 | } |
| 473 | |
| 474 | private static String bytesToHex(byte[] bytes) { |
| 475 | char[] hexArray = "0123456789abcdef".toCharArray(); |