Skip to content

Instantly share code, notes, and snippets.

@guilhermesgb
Last active September 19, 2017 22:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guilhermesgb/4146c7233193d924acca3ef610319f98 to your computer and use it in GitHub Desktop.
Save guilhermesgb/4146c7233193d924acca3ef610319f98 to your computer and use it in GitHub Desktop.
Generating a PagarMe CardHash manually using Java / Android
import android.util.Base64;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
//...
Cipher cipher;
KeyFactory keyFactory;
try {
cipher = Cipher.getInstance("RSA/None/PKCS1PADDING");
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException | NoSuchPaddingException cardHashGenerationImpossible) {
//DEVICE (IF ANDROID) OR JAVA ENVIRONMENT UNABLE TO GENERATE CARD HASHES
//AS IT WON'T BE ABLE TO PROPERLY ENCRYPT USER CARD INFORMATION.
//AS PER https://docs.pagar.me/api/?shell#gerando-card_hash-manualmente,
//PAGARME REQUIRES PUBLIC CRYPTOGRAPHY USING RSA W/ PKCS1Padding.
}
//...
//USING RETROFIT TO GET https://api.pagar.me/1/transactions/card_hash_key.
Call<JsonObject> fetchPagarMeCardHashPublicKey = AppApi.getInstance()
.getPagarMeCardHashPublicKey(Constants.PAGAR_ME_ENCRYPTION_KEY);
fetchPagarMeCardHashPublicKey.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.isSuccessful() && response.body() != null) {
try {
JsonObject responseBody = response.body();
int cardHashId = responseBody.get("id").getAsInt();
String rawPublicKey = responseBody.get("public_key").getAsString();
//PAGARME PUBLIC KEYS COME IN PEM FORMAT, SO WE NEED TO CONVERT'EM
//TO DER FORMAT SO THAT THEY CAN PLAY NICE WITH X509EncodedKeySpec.
rawPublicKey = rawPublicKey
.replaceAll("\\s*-----BEGIN PUBLIC KEY-----\\s*", "")
.replaceAll("\\s*-----END PUBLIC KEY-----\\s*", "")
.replaceAll("\\s", "");
byte[] decodedPublicKey = Base64.decode(rawPublicKey.getBytes("UTF-8"), 0);
//SUCCESSFULLY CONVERTED THE PUBLIC KEY TO DER FORMAT.
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//NOW FORMATTING CARD INFORMATION IN THE FORMAT EXPECTED BY PAGARME.
String cardInformation = String.format(Locale.US,
"card_number=%s&card_holder_name=%s&card_expiration_date=%s"
+ "&card_cvv=%s", creditCardNumber.replace(" ", "").trim(),
URLEncoder.encode(profileCreditCardName.getText().trim(), "UTF-8").replace("+", "%20"),
creditCardGoodThru.replace("/", "").trim(), profileCreditCardCvc.getText().trim());
//THEN WE USE OUR CIPHER TO ENCRYPT AND THEN BASE64-ENCODE THE CARD INFORMATION,
//AND FINALLY, APPEND THE ASSIGNED CARD ID AS PREFIX OF THE RESULT TO COMPOSE THE CARD HASH.
byte[] encryptedCardInformation = cipher.doFinal(cardInformation.getBytes("UTF-8"));
String cardHash = String.format(Locale.US, "%d_%s", cardHashId,
(Base64.encodeToString(encryptedCardInformation, Base64.DEFAULT)))
.replaceAll("\\s", "");
//NOW YOU MIGHT WANT TO SEND THE CARD HASH TO YOUR BACKEND SERVER.
} catch (InvalidKeySpecException | InvalidKeyException invalidKey) {
//PROBLEMS WITH THE PUBLIC KEY RECEIVED FROM PAGARME.
} catch (BadPaddingException | IllegalBlockSizeException | IOException encryptionException) {
//I/O ERRORS HAPPENED WHILE TRYING TO ENCRYPT CARD INFORMATION.
}
} else {
//PAGARME PROBABLY DIDN'T LIKE THE PAGAR_ME_ENCRYPTION_KEY YOU USED IN THE GET REQUEST...
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable throwable) {
//COULD NOT RECEIVE PUBLIC KEY FROM PAGARME.
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment