Tests unitaires pour le fichier AdeptActivate.java et ses classes associées. La classe AdeptActivateCli.java n'est pas inclue.

This commit is contained in:
2025-10-24 17:46:05 -07:00
parent 6c0155986f
commit c472fa04bf
5 changed files with 578 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
import common.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;
import java.util.Comparator;
import java.util.Map;
import java.util.logging.Level;
import static common.Activation.HOBBES_DEFAULT_VERSION;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.junit.jupiter.api.Assertions.*;
class AdeptActivateTest
{
@SuppressWarnings("FieldCanBeLocal")
private String publicAuthKey;
@BeforeAll
static void setupBouncyCastle() {
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
}
private Device device;
private Activation activation;
private final Path dirPath = Path.of( "src/test", "resources" );
private AdeptActivate activator;
public static void deleteDirectoryWithContents( Path directoryPath ) throws IOException
{
// Check if the path exists and is a directory
if (Files.exists( directoryPath ) && Files.isDirectory( directoryPath ))
{
// Walk the file tree in depth-first order (reverse order for deletion)
Files.walk( directoryPath )
.sorted( Comparator.reverseOrder() ) // Sort in reverse to delete contents before parent directory
.forEach( path -> {
try
{
Files.delete( path ); // Delete each file or directory
}
catch (IOException ignore) {}
} );
}
}
@Test
void createActivation()
throws NoSuchAlgorithmException, IOException, ParserConfigurationException, SAXException
{
Path tempPath = Paths.get( dirPath.toString(), "temp" );
deleteDirectoryWithContents( tempPath );
Files.createDirectories( tempPath );
// copy in a constant key file so we can use it to decrypt.
Files.copy( Path.of( dirPath.toString(), "devicesalt"),
Path.of( tempPath.toString(), "devicesalt") , REPLACE_EXISTING );
device = new Device( tempPath.resolve( "device.xml" ), tempPath.resolve( "devicesalt" ),
HOBBES_DEFAULT_VERSION, true, Level.WARNING );
// Make sure files got created
assertTrue( Files.exists( Path.of( tempPath.toString(), "devicesalt" ) ));
assertTrue( Files.exists( Path.of( tempPath.toString(), "device.xml" ) ));
activation = Activation.createActivation( tempPath.resolve( "activation.xml" ),
"localhost", new MockHttpUtils( device ), Level.WARNING );
// Only 5 properties at this point. Check size and activationURL
assertEquals( 5, activation.getPropertiesSize() );
assertEquals( "http://localhost/adept", activation.getActivationURL());
}
@Test
void loadActivation()
throws NoSuchAlgorithmException, IOException, ParserConfigurationException, SAXException
{
device = new Device( dirPath.resolve( "device.xml" ), dirPath.resolve( "devicesalt" ),
HOBBES_DEFAULT_VERSION, true, Level.FINEST );
activation = Activation.createActivation( dirPath.resolve( "activation.xml" ),
"localhost", new MockHttpUtils( device ), Level.FINEST );
assertEquals( 15, activation.getPropertiesSize() );
// Did credentials get loaded?
assertEquals( "urn:uuid:26031c45-3be6-46fd-9a66-0457b0b8c2fc", activation.getUUID());
// Did the license server info get loaded?
Map<String, String> services = activation.getLicenseServices();
assertTrue( services.containsKey( "https://nasigningservice.adobe.com/licensesign" ) );
assertTrue( activation
.getLicenseServiceCertificate( "https://nasigningservice.adobe.com/licensesign" )
.startsWith( "MIIEvjCCA6agAwIBAgIER2q5ljANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMx" ));
}
@Test
void signIn()
throws GeneralSecurityException, IOException, ParserConfigurationException, SAXException
{
createActivation(); // This creates new activation files in the temp directory
Path tempPath = Paths.get( dirPath.toString(), "temp" );
activator = new AdeptActivate( activation, device, tempPath.toString() );
Document signInRequest = activator.buildSignInRequest( "anonymous", "",
activation.getAuthenticationCertificate() );
// save the public auth key so we can use it later.
NodeList els = signInRequest.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS,
"publicAuthKey" );
publicAuthKey = els.item( 0 ).getTextContent();
els = signInRequest.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS,
"encryptedPrivateLicenseKey" );
String privateKey = els.item( 0 ).getTextContent();
byte[] encrypted = Base64.getDecoder().decode( privateKey );
SecretKeySpec secretKey = new SecretKeySpec( device.getDeviceKey(), "AES" );
privateKey = Base64.getEncoder().encodeToString( BCCrypto.decrypt( encrypted, secretKey ));
activator.signIn( signInRequest );
assertEquals( 11, activation.getPropertiesSize() );
String privateLicenseKey = activation.getPrivateLicenseKey();
assertEquals( privateKey, privateLicenseKey );
}
@Test
void activateDevice()
throws GeneralSecurityException, IOException, ParserConfigurationException, SAXException
{
signIn();
Document activationRequest = activator.buildActivateReq();
activator.activateDevice( activationRequest );
assertEquals( 15, activation.getPropertiesSize() );
}
@Test
void exportPrivateLicenseKey()
throws NoSuchAlgorithmException, IOException, ParserConfigurationException, SAXException
{
File[] filesToDelete = dirPath.toFile().listFiles(
file -> {
return file.isFile()
&& ( file.getName().matches(".*\\.der")
|| file.getName().matches(".*\\.pem")); // Example: matches all .txt files
} );
for (File fileToDelete : filesToDelete)
{
try
{
Files.delete( Path.of( fileToDelete.getPath() ) );
}
catch (IOException ignore){}
}
loadActivation();
activator = new AdeptActivate( activation, device, dirPath.toString() );
byte[] key = activator.exportPrivateLicenseKey();
assertNotNull( key );
String uuid = activation.getUUID();
uuid = uuid.substring( uuid.lastIndexOf('-' ) );
Path keyPath = Paths.get( dirPath.toString(), "anonymous"+uuid+".pem" );
assertTrue( Files.exists( keyPath ));
keyPath = Paths.get( dirPath.toString(), "anonymous"+uuid+".der" );
assertTrue( Files.exists( keyPath ));
}
}

View File

@@ -0,0 +1,93 @@
package common;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import static javax.crypto.Cipher.DECRYPT_MODE;
public class BCCrypto
{
static
{
Security.addProvider( new BouncyCastleProvider() );
}
static String uuid = "urn:uuid:28ab4b64-db75-4f76-a69a-c00e04225bf6";
public static byte[] decrypt( byte[] encryptedPrivateKey, SecretKeySpec secretKey )
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException
{
byte[] iv = new byte[16];
System.arraycopy( encryptedPrivateKey, 0, iv, 0, 16 );
byte[] encryptedData = new byte[encryptedPrivateKey.length - 16];
System.arraycopy( encryptedPrivateKey, 16, encryptedData, 0, encryptedPrivateKey.length - 16);
Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding", "BC" );
cipher.init( DECRYPT_MODE, secretKey, new IvParameterSpec( iv ) );
return cipher.doFinal( encryptedData );
}
public static X509Certificate createSSCertificate( byte[] publicKeyData, byte[] privateKeyData )
throws CertificateException, OperatorCreationException, NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeySpecException
{
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyData);
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privateKeyData);
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
{
ASN1ObjectIdentifier customOid = new ASN1ObjectIdentifier("2.5.4.6");
X500NameBuilder subjectBuilder = new X500NameBuilder( BCStyle.INSTANCE);
subjectBuilder.addRDN(customOid, uuid ); // Add your custom OID and value
X500Name subjectDN = subjectBuilder.build();
// Certificate details
X500Name subject = new X500Name( "CN=MySelfSignedCert, O=MyOrg" );
BigInteger serial = BigInteger.valueOf( System.currentTimeMillis() );
Date notBefore = new Date( System.currentTimeMillis() - 1000L * 60 * 60 * 24 ); // 1 day ago
Date notAfter = new Date( System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 3650 ); // 10 years from now
// Build the certificate
PrivateKey privateKey = keyFactory.generatePrivate(privKeySpec);
PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
subject, serial, notBefore, notAfter, subjectDN, publicKey);
ContentSigner contentSigner = new JcaContentSignerBuilder( "SHA256WithRSA" )
.setProvider( "BC" )
.build( privateKey );
X509Certificate certificate = new org.bouncycastle.cert.jcajce.JcaX509CertificateConverter()
.getCertificate( certBuilder.build( contentSigner ) );
String b64 = Base64.getEncoder().encodeToString( certificate.getEncoded() );
return certificate;
}
}
}

View File

@@ -0,0 +1,300 @@
package common;
import org.bouncycastle.asn1.*;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.pkcs.*;
import org.bouncycastle.pkcs.jcajce.JcaPKCS12SafeBagBuilder;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.pkcs.jcajce.JcePKCS12MacCalculatorBuilder;
import org.bouncycastle.pkcs.jcajce.JcePKCSPBEOutputEncryptorBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.security.*;
import static common.BCCrypto.decrypt;
import static common.BCCrypto.uuid;
import static common.WinDevice.hexStringToByteArray;
import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;
import static org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.pkcs_9_at_friendlyName;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class MockHttpUtils extends HttpUtils
{
private final Device device;
String mockResponsePath = "src/test/resources/mockServerResponses";
private PublicKey publicKey;
public MockHttpUtils( Device device )
{
Security.addProvider( new BouncyCastleProvider() );
this.device = device;
}
@Override
public String HTTPSendRequest( String urlString, String postData, String contentType,
Map<String, String> responseHeaders, String outputFilePath, boolean resume )
{
try
{
if ("localhost/ActivationServiceInfo".equalsIgnoreCase( urlString ))
{
// return the mock activation data, modified for localhost
return Files.readString( Paths.get( mockResponsePath, "activationInfo.xml" ) );
}
else if ("http://localhost/adept/AuthenticationServiceInfo".equalsIgnoreCase( urlString ))
{
// Lots of data here, most of which is discarded, but we keep it for completeness
return Files.readString( Paths.get( mockResponsePath, "authServiceInfo.xml" ) );
}
else if ("http://localhost/adept/SignInDirect".equalsIgnoreCase( urlString ))
{
return createSignInResponse( postData );
}
else if ("http://localhost/adept/Activate".equalsIgnoreCase( urlString ))
{
return createActivationResponse( postData );
}
return null;
}
catch (IOException | ParserConfigurationException | SAXException | GeneralSecurityException |
OperatorCreationException e)
{
LOGGER.log( Level.SEVERE, "HTTP Request error: " + e.getMessage(), e );
throw new GourouException( "HTTP Request failed", e );
}
catch (PKCSException e)
{
throw new RuntimeException( e );
}
}
private String createActivationResponse( String activationRquest )
throws IOException, ParserConfigurationException, SAXException, NoSuchAlgorithmException,
NoSuchPaddingException, NoSuchProviderException, InvalidKeyException, IllegalBlockSizeException,
BadPaddingException
{
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
fac.setNamespaceAware( true );
DocumentBuilder db = fac.newDocumentBuilder();
Document requestDoc = db.parse( new ByteArrayInputStream( activationRquest.getBytes() ) );
requestDoc.getDocumentElement().normalize();
Element activationToken = requestDoc.getDocumentElement();
NodeList els = requestDoc.getElementsByTagNameNS(
XmlUtils.ADOBE_ADEPT_NS, "signature" );
Node sigNode = els.item( 0 );
activationToken.removeChild( sigNode );
ByteArrayOutputStream xer = new ByteArrayOutputStream();
//noinspection Convert2Diamond
XmlUtils.xml2ASN( activationToken, new HashMap<String,String>(), xer );
MessageDigest shaMd = MessageDigest.getInstance( "SHA1" );
// the signature as I compute it
String signature = Base64.getEncoder().encodeToString( shaMd.digest( xer.toByteArray() ) );
// now get the attached signature, decrypt it with the public key, and see if it matches.
String originalSig = sigNode.getTextContent();
Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding", "BC" );
cipher.init( DECRYPT_MODE, publicKey );
byte[] enc = cipher.doFinal( Base64.getDecoder().decode( originalSig ));
originalSig = Base64.getEncoder().encodeToString( enc );
if (!signature.equals( originalSig ))
System.out.println( "Signatures do not match" );
Document responseDoc = db.newDocument();
responseDoc.appendChild( responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "activationToken" ) );
Element token = responseDoc.getDocumentElement();
token.setAttribute( "xmlns", XmlUtils.ADOBE_ADEPT_NS );
Element child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "device" );
child.setTextContent( "urn:uuid:f163499a-1dc7-41fd-9ec9-fcf69c8eae18" );
token.appendChild( child );
NodeList elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "fingerprint" );
String text = elementList.item( 0 ).getTextContent();
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "fingerprint" );
child.setTextContent( text );
token.appendChild( child );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "deviceType" );
child.setTextContent( "standalone" );
token.appendChild( child );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "activationURL" );
child.setTextContent( "http://localhost/activation/adept" );
token.appendChild( child );
elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "user" );
text = elementList.item( 0 ).getTextContent();
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "user" );
child.setTextContent( text );
token.appendChild( child );
// This will fail the signature check...
String fauxSig = "S4rgc/FJkfK7BbFCrbKNs+SznA+OZfv2TER2vP511YevEUBOupkCw0E2R2u3ohpp0WQV7ds2vKJ6K4oQOlUuuO9e7jElDiaIQa77LOLnKpTl37lcbKR1cPCOEzUlsM7tBZUtdHM+CB5Iy+Yh624zHWFf8zDfGv6aKyPGL948OMo=";
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "signature" );
child.setTextContent( fauxSig );
token.appendChild( child );
return XmlUtils.docToString( responseDoc, true );
}
private String createSignInResponse( String signInRequest )
throws ParserConfigurationException, IOException, SAXException, GeneralSecurityException,
OperatorCreationException, PKCSException
{
Base64.Decoder b64Decoder = Base64.getDecoder();
Base64.Encoder b64Encoder = Base64.getEncoder();
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
fac.setNamespaceAware( true );
DocumentBuilder db = fac.newDocumentBuilder();
Document requestDoc = db.parse( new ByteArrayInputStream( signInRequest.getBytes() ) );
requestDoc.getDocumentElement().normalize();
Document responseDoc = db.newDocument();
responseDoc.appendChild( responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "credentials" ) );
Element credentials = responseDoc.getDocumentElement();
credentials.setAttribute( "xmlns", XmlUtils.ADOBE_ADEPT_NS );
Element child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "user" );
child.setTextContent( uuid );
credentials.appendChild( child );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "username" );
child.setAttribute( "method", "anonymous" );
credentials.appendChild( child );
NodeList elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "publicAuthKey" );
byte[] publicAuthKey = b64Decoder.decode( elementList.item( 0 ).getTextContent() );
elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "encryptedPrivateAuthKey" );
byte[] privateAuthKey = b64Decoder.decode( elementList.item( 0 ).getTextContent() );
SecretKeySpec secretKey = new SecretKeySpec( device.getDeviceKey(), "AES" );
byte[] decryptedAuthKey = decrypt( privateAuthKey, secretKey );
X509Certificate certificate = BCCrypto.createSSCertificate( publicAuthKey, decryptedAuthKey );
publicKey = certificate.getPublicKey(); // pretend we're the server, and save this for later
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec( decryptedAuthKey );
PrivateKey privateKey = KeyFactory.getInstance( "RSA", "BC" )
.generatePrivate( keySpec );
String dk = Base64.getEncoder().encodeToString( device.getDeviceKey() );
char[] keyPassword = dk.toCharArray();
JcePKCSPBEOutputEncryptorBuilder encBuilder =
new JcePKCSPBEOutputEncryptorBuilder( PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC );
encBuilder.setProvider( "BC" );
OutputEncryptor outputEncryptor = encBuilder.build( keyPassword );
JcaPKCS12SafeBagBuilder safeBagBuilder =
new JcaPKCS12SafeBagBuilder( privateKey, outputEncryptor );
safeBagBuilder.addBagAttribute( pkcs_9_at_friendlyName, new org.bouncycastle.asn1.DERBMPString( uuid ) );
byte[] data = hexStringToByteArray( "54696D652031373531363730383233323636" );
DEROctetString octetString = new DEROctetString(data);
safeBagBuilder.addBagAttribute( PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
ASN1OctetString.getInstance( new DEROctetString( octetString.getEncoded() )));
// Build the PKCS#12 Pfx structure
PKCS12PfxPduBuilder pfxPduBuilder = new PKCS12PfxPduBuilder();
pfxPduBuilder.addData( safeBagBuilder.build() );
pfxPduBuilder.addEncryptedData( outputEncryptor, safeBagBuilder.build() );
// Build the Pfx object with MAC protection
char[] pfxPassword = "".toCharArray();
org.bouncycastle.pkcs.PKCS12PfxPdu pfx = pfxPduBuilder.build( new JcePKCS12MacCalculatorBuilder(),
pfxPassword );
String pkcs12 = Base64.getEncoder().encodeToString( pfx.getEncoded() );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "pkcs12" );
child.setTextContent( pkcs12 );
credentials.appendChild( child );
// reencrypt the private key and add it to the response.
elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "encryptedPrivateLicenseKey" );
String b64 = elementList.item( 0 ).getTextContent();
byte[] privateLicKey = b64Decoder.decode( b64 );
byte[] decryptedLicenseKey = decrypt( privateLicKey, secretKey );
Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding", "BC" );
cipher.init( ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal( decryptedLicenseKey );
byte[] iv = cipher.getIV();
byte[] finalEncrypteData = new byte[16 + encryptedData.length];
System.arraycopy( iv, 0, finalEncrypteData, 0, 16 );
System.arraycopy( encryptedData, 0, finalEncrypteData, 16, encryptedData.length );
b64 = b64Encoder.encodeToString( finalEncrypteData );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "encryptedPrivateLicenseKey" );
child.setTextContent( b64 );
credentials.appendChild( child );
elementList = requestDoc.getElementsByTagNameNS( XmlUtils.ADOBE_ADEPT_NS, "publicLicenseKey" );
byte[] publicLicKey = b64Decoder.decode( elementList.item( 0 ).getTextContent() );
certificate = BCCrypto.createSSCertificate( publicLicKey, decryptedLicenseKey );
b64 = b64Encoder.encodeToString( certificate.getEncoded() );
child = responseDoc.createElementNS( XmlUtils.ADOBE_ADEPT_NS, "licenseCertificate" );
child.setTextContent( b64 );
credentials.appendChild( child );
return XmlUtils.docToString( responseDoc, false );
}
private void testEncryption( byte[] data, String pkcs12, String alias, byte[] key )
throws IOException, GeneralSecurityException
{
Base64.Decoder decoder = Base64.getDecoder();
byte[] pkcs12Data = decoder.decode( pkcs12 );
ByteArrayInputStream inputStream = new ByteArrayInputStream( pkcs12Data) ;
KeyStore keyStore = KeyStore.getInstance( "PKCS12" );
// Load the keystore from the input stream and password
keyStore.load( inputStream, null );
String dk = Base64.getEncoder().encodeToString( key );
char[] keyPassword = dk.toCharArray();
// this keystore contains a private key entry, but may not have a public key certificate!
RSAPrivateKey rsaKey = (RSAPrivateKey) keyStore.getKey( alias, keyPassword );
Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" );
cipher.init( ENCRYPT_MODE, rsaKey );
byte[] enc = cipher.doFinal( data );
cipher.init( DECRYPT_MODE, publicKey );
byte[] decrypted = cipher.doFinal( enc );
System.out.println( Base64.getEncoder().encodeToString( decrypted ));
}
}

View File

@@ -0,0 +1,5 @@
<activationServiceInfo xmlns="http://ns.adobe.com/adept">
<authURL>http://localhost/adept</authURL>
<userInfoURL>http://localhost/adept</userInfoURL>
<certificate>MIIEsjCCA5qgAwIBAgIER2q5eDANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMRswGQYDVQQLExJEaWdpdGFsIFB1Ymxpc2hpbmcxMzAxBgNVBAMTKkFkb2JlIENvbnRlbnQgU2VydmVyIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wODAxMDkxODM3NDVaFw0xMzAxMDkxOTA3NDVaMH0xCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEbMBkGA1UECxMSRGlnaXRhbCBQdWJsaXNoaW5nMSwwKgYDVQQDEyNodHRwOi8vYWRlYWN0aXZhdGUuYWRvYmUuY29tL2FkZXB0LzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyXpCCWFh0Q3Bi1S7xf+CJfMd+cZz3HB0NknDScB1Cs8KdU0ygO7iqAgdiAdPliITkUTVEgUPvK+4yYCUderzBjq13/IrKlwEAyWeNgssJekpYgqNywo7Md1OApXzM47wVThNePNydhGYuNEEDDxzO+0JxucfhfArwnp7kIWA6q8CAwEAAaOCAbQwggGwMAsGA1UdDwQEAwIFoDBYBglghkgBhvprHgEESwxJVGhlIHByaXZhdGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBjZXJ0aWZpY2F0ZSBtYXkgaGF2ZSBiZWVuIGV4cG9ydGVkLjAUBgNVHSUEDTALBgkqhkiG9y8CAQQwgbIGA1UdIASBqjCBpzCBpAYJKoZIhvcvAQIDMIGWMIGTBggrBgEFBQcCAjCBhhqBg1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50IGFjY29tcGFueWluZyB0aGUgQWRvYmUgc29mdHdhcmUuMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Fkb2JlQ1MuY3JsMB8GA1UdIwQYMBaAFIvu8IFgyaLaHg5SwVgMBLBD94/oMB0GA1UdDgQWBBT9A+kXOPL6N57MN/zovbCGEx2+BTAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBQUAA4IBAQBVjUalliql3VjpLdT8si7OwPU1wQODllwlgfLH7tI/Ubq5wHDlprGtbf3jZm6tXY1qmh9mz1WnTmQHU3uPk8qgpihrpx4HJTjhAhLP0CXU1rd/t5whwhgT1lYfw77RRG2lZ5BzpHb/XjnY5yc3awd6F3Dli6kTkbcPyOCNoXlW4wiF+jkL+jBImY8xo2EewiJioY/iTYZH5HF+PjHF5mffANiLK/Q43l4f0YF8UagTfAJkD3iQV9lrTOWxKBgpfdyvekGqFCDq9AKzfpllqctxsC29W5bXU0cVYzf6Bj5ALs6tyi7r5fsIPSwszH/i4ixsuD0qccIgTXCwMNbt9zQu</certificate>
</activationServiceInfo>

File diff suppressed because one or more lines are too long