Reputation: 71
I am probably missing something very simple and stupid - I'd greatly appreciate any and all hints.
What I am trying to achieve is to produce a signature as per Apple's doc
Sign.java contents:
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
public class Sign {
public static final String SKAD_SIGNING_ALGORITHM = "SHA256withECDSA";
public static void main(String[] args) throws Exception {
byte[] keyBytes = Files.readAllBytes(Path.of(args[0]));
KeyFactory kf = KeyFactory.getInstance("EC");
PKCS8EncodedKeySpec pkcs8EncodedKey = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey key = kf.generatePrivate(pkcs8EncodedKey);
Signature ecdsa = Signature.getInstance(SKAD_SIGNING_ALGORITHM);
ecdsa.initSign(key);
ecdsa.update(System.in.readAllBytes());
byte[] realSig = ecdsa.sign();
System.out.write(realSig);
}
}
Produce the signature w/ openssl:
$ cat $(test_doc) | java -cp src Sign <(openssl pkcs8 -in $(private_key) -inform PEM outform DER -nocrypt -topk8) >$(java_signature)
... and verify the sig:
$ openssl dgst -sha256 -verify $(public_key) -signature $(java_signature) $(test_doc)
$(test_doc) - being simple message to be signed\
$(private_key) - pkcs#8 private key\
$(public_key) - pkcs#8 public key
Works fine!
When I try to produce a signature like this:
@Test
public void SimplestSkadSignTest()
throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeySpecException,
InvalidKeyException {
String SKAD_SIGNING_ALGORITHM = "SHA256withECDSA";
String MESSAGE = "hello world";
byte[] keyBytes = SKAdHelper.class
.getResourceAsStream("/private_key_in_der_format.der").readAllBytes();
KeyFactory kf = KeyFactory.getInstance("EC");
PKCS8EncodedKeySpec pkcs8EncodedKey = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey key = kf.generatePrivate(pkcs8EncodedKey);
Signature ecdsa = Signature.getInstance(SKAD_SIGNING_ALGORITHM);
ecdsa.initSign(key);
ecdsa.update(MESSAGE.getBytes(StandardCharsets.UTF_8));
byte[] realSig = ecdsa.sign();
System.out.print(Base64.getEncoder().encodeToString(realSig));
ByteSink byteSink = MoreFiles.asByteSink(Path.of("/dump/anywhere/sig.bin"));
byteSink.write(realSig);
}
OpenSSL won't validate the produced sig.bin
$ openssl dgst -sha256 -verify $(public_key) -signature sig.bin $(test_doc)
Verification Failure
Both ways seem the same to me - what am I missing here folks?
Upvotes: 1
Views: 163
Reputation: 71
Tldr: both work. Problem was between my chair and the keyboard :-)
@dave_thompson_085 was on point, to be precise:
$ hexdump -C message.txt
00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
0000000c
String MESSAGE = "hello world";
... but it is not. Dumped from java to file:
ByteSink byteSink = MoreFiles.asByteSink(Path.of("/cleartext_message.txt"));
byteSink.write(MESSAGE.getBytes(StandardCharsets.UTF_8));
internally looks like this:
$ hexdump -C message_java.txt
00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 |hello world|
0000000b
Upvotes: 1