Created
November 2, 2020 13:12
-
-
Save oded-regev/01a9c2b120204feb47cca5a9e5644192 to your computer and use it in GitHub Desktop.
Prepare the Signature for SkAdNetwork iOS14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main.java.com.abccompany.example; | |
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.nio.charset.StandardCharsets; | |
import java.security.*; | |
import java.security.spec.PKCS8EncodedKeySpec; | |
import java.util.Base64; | |
import java.util.regex.Pattern; | |
public class SignaturePoc { | |
public static void main(String[] args) throws Exception { | |
final String AdNetworkVersion = "2.0"; | |
final String AdNetworkIdentifier = "97r2b46746.skadnetwork"; // ABC AdNetwork ID on Apple | |
final String AdNetworkCampaignIdentifier = "99"; | |
final String ITunesItemIdentifier = "711455226"; // Forge of Empires App Store Page | |
final String AdNetworkNonce = "e7b315b5-5d3d-4ceb-bb90-b617dee5e173"; | |
final String SourceAppStoreIdentifier = "331786748"; // CNN App Store page | |
final String ParameterAdNetworkTimestamp = "1598441577"; // The Current Unix Timestamp | |
final String prepareSignatureForV1 = AdNetworkIdentifier + '\u2063' + AdNetworkCampaignIdentifier + '\u2063' + ITunesItemIdentifier + '\u2063' + AdNetworkNonce + '\u2063' + ParameterAdNetworkTimestamp; | |
final String prepareSignatureForV2 = AdNetworkVersion + '\u2063' + AdNetworkIdentifier + '\u2063' + AdNetworkCampaignIdentifier + '\u2063' + ITunesItemIdentifier + '\u2063' + AdNetworkNonce + '\u2063' + SourceAppStoreIdentifier + '\u2063' + ParameterAdNetworkTimestamp; | |
System.out.println("--- Version 1.0 ---"); | |
signStringMessage(prepareSignatureForV1); | |
System.out.println("\n\n--- Version 1.0 ---"); | |
signStringMessage(prepareSignatureForV2); | |
} | |
static private String signStringMessage(String msg) throws Exception { | |
System.out.println("signStringMessage: " + msg); | |
final String ALGO = "SHA256withECDSA"; | |
KeyFactory kf = KeyFactory.getInstance("EC"); | |
byte[] keyBytesArray = loadPEM("file.pem"); | |
PKCS8EncodedKeySpec pkcs8EncodedKey = new PKCS8EncodedKeySpec(keyBytesArray); | |
PrivateKey key = kf.generatePrivate(pkcs8EncodedKey); | |
/* | |
* Create a Signature object and initialize it with the private key | |
*/ | |
Signature ecdsa = Signature.getInstance(ALGO); | |
ecdsa.initSign(key); | |
byte[] strByte = msg.getBytes("UTF-8"); | |
ecdsa.update(strByte); | |
/* | |
* Now that all the data to be signed has been read in, generate a | |
* signature for it | |
*/ | |
byte[] realSig = ecdsa.sign(); | |
// https://developer.apple.com/documentation/storekit/skadnetwork/generating_the_signature_to_validate_an_installation#3627357 | |
// Encode the binary signature you generated into a Base64 string. | |
String sig = Base64.getEncoder().encodeToString(realSig); | |
System.out.println("Signature: " + sig); | |
return sig; | |
} | |
static private byte[] loadPEM(String fileName) throws IOException { | |
ClassLoader classloader = Thread.currentThread().getContextClassLoader(); | |
InputStream in = classloader.getResourceAsStream(fileName); | |
String pem = new String(readAllBytes(in), StandardCharsets.ISO_8859_1); | |
Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*"); | |
String encoded = parse.matcher(pem).replaceFirst("$1"); | |
return Base64.getMimeDecoder().decode(encoded); | |
} | |
static byte[] readAllBytes(InputStream in) throws IOException { | |
ByteArrayOutputStream baos= new ByteArrayOutputStream(); | |
byte[] buf = new byte[1024]; | |
for (int read=0; read != -1; read = in.read(buf)) { baos.write(buf, 0, read); } | |
return baos.toByteArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment