1 package org
.asamk
.signal
.manager
.util
;
3 import org
.signal
.libsignal
.protocol
.IdentityKey
;
4 import org
.signal
.libsignal
.protocol
.IdentityKeyPair
;
5 import org
.signal
.libsignal
.protocol
.ecc
.ECPrivateKey
;
6 import org
.signal
.libsignal
.protocol
.ecc
.ECPublicKey
;
7 import org
.slf4j
.Logger
;
8 import org
.slf4j
.LoggerFactory
;
9 import org
.whispersystems
.signalservice
.internal
.push
.PaymentAddress
;
11 import okio
.ByteString
;
13 public class PaymentUtils
{
15 private static final Logger logger
= LoggerFactory
.getLogger(PaymentUtils
.class);
17 private PaymentUtils() {
21 * Signs the supplied address bytes with the {@link IdentityKeyPair}'s private key and returns a proto that includes it, and it's signature.
23 public static PaymentAddress
signPaymentsAddress(byte[] publicAddressBytes
, ECPrivateKey privateKey
) {
24 byte[] signature
= privateKey
.calculateSignature(publicAddressBytes
);
26 return new PaymentAddress
.Builder().mobileCoin(new PaymentAddress
.MobileCoin
.Builder().publicAddress(ByteString
.of(
27 publicAddressBytes
)).signature(ByteString
.of(signature
)).build()).build();
31 * Verifies that the payments address is signed with the supplied {@link IdentityKey}.
33 * Returns the validated bytes if so, otherwise returns null.
35 public static byte[] verifyPaymentsAddress(PaymentAddress paymentAddress
, ECPublicKey publicKey
) {
36 final var mobileCoinAddress
= paymentAddress
.mobileCoin
;
37 if (mobileCoinAddress
== null
38 || mobileCoinAddress
.publicAddress
== null
39 || mobileCoinAddress
.signature
== null) {
40 logger
.debug("Got payment address without mobile coin address, ignoring.");
44 byte[] bytes
= mobileCoinAddress
.publicAddress
.toByteArray();
45 byte[] signature
= mobileCoinAddress
.signature
.toByteArray();
47 if (signature
.length
!= 64 || !publicKey
.verifySignature(bytes
, signature
)) {
48 logger
.debug("Got mobile coin address with invalid signature, ignoring.");