簡體   English   中英

PublicKey處理Java / PHP

[英]PublicKey handling Java / PHP

我目前陷入了RSA密鑰管理的問題。 具體來說,我想在Java中創建RSA密鑰對,簽署一些內容(即字符串)將公鑰,簽名和簽名的String導出到JSON文件中(是​​的,JSON!),將其導入另一個服務器使用PHP,並驗證簽名,這意味着我必須從JSON數據重新創建一個可用的密鑰。

另外,我必須反過來做(在PHP中創建,在Java中驗證)

另外,我需要將私鑰導出為JSON(是的,JSON再次:)!並導出它。

所以在Java方面,一切似乎都很順利。 我可以創建密鑰,將它們導出為JSON,重新導入它們並使用它們。 創建和驗證簽名沒有問題。 這是代碼:

創建密鑰對:

public static final String  ALGORITHM           = "RSA";
public static final int     KEYSIZE             = 4096;
public static KeyPair createKeyPair() throws NoSuchAlgorithmException {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
    keyPairGenerator.initialize(KEYSIZE);

    return keyPairGenerator.genKeyPair();
}

將密鑰導出到String(最終將在JSON對象中) - 私鑰的代碼類似:

public static final String  PUBLICKEY_PREFIX    = "-----BEGIN PUBLIC KEY-----";
public static final String  PUBLICKEY_POSTFIX   = "-----END PUBLIC KEY-----";
public static String exportPublicKey(Key key) {
    return PUBLICKEY_PREFIX + DatatypeConverter.printBase64Binary(key.getEncoded()) + PUBLICKEY_POSTFIX;
}

例如,上述結果將是

"-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtBPxEtEWws2pPN5HCB795+nQyX23ZTKJt5PoMQQpwjOY/7U5ODkwHpuHWUhAuB1qTKTUdEWbe5x7WkD6/ksSib64Xq3jIeLQrfhj+g3bGsQjtca5LyIZ/J+G55l7k/Ny/lfQQNfquCcILHW7DrnzTb0D56IOBsR/r0Vv8ZvUxnaXUQtif8Q6dme8uoqzfnF46McqThnvPDxdHmhumb7tqPffzt35bRxFBvMcAWqW0FcPAeXD6cmsOBAATh/gVe1g5J89FyK8PhkNjW3uLMmknCTQg9KoWh4+DDRrLXxqSCBbaIRMCtbhShZOIbtjurJ+ZjhR/WSPnzJrl84rTjWG3Po6jsdtJ0pRHP4YnXXXJWhMt2oTOtHTQj4+99UX7Yuyp2tmFaEdQXvm3k/qbT9PBlwEovC2yqbFMcrM7sAW09NiSDdm1ipzV+vsOGuRXF2vtNX6pplifp5va5hQY/UqmlHSygvecImP5ennFOP7G62W/Q0w0qRzOXmFHN6Hsi8D1ZlWwgjyNahoX2yvgBMzy7MMYJcqiS9GOOETaenXTZViiipceGk96crjh6LG7RudMb+WN2yRXnjdWYd0GYPsaXz/faMohfXRXzRq/oIGZ4EdHhp9TknL2rCZmfR3N4Ozi1BkszAmmQeeNrUgxEjB8TdSer4p4DfR22NFcs9M3YkCAwEAAQ==-----END PUBLIC KEY-----"

然后,我再次從JSON中讀取鍵:

public static PublicKey importPublicKey(String key) throws InvalidKeySpecException, NoSuchAlgorithmException  {
    key = stripKey(key);
    byte[] keyBytes = DatatypeConverter.parseBase64Binary(key);
    return KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(keyBytes));
}

public static PrivateKey importPrivateKey(String key) throws InvalidKeySpecException, NoSuchAlgorithmException  {
    key = stripKey(key);
    byte[] keyBytes = DatatypeConverter.parseBase64Binary(key);
    return KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
}

這對我來說很好。 我可以創建,存儲,重新導入和使用密鑰 - 包括公鑰和私鑰。 我創建的簽名使用

public static String createSignature(PrivateKey privateKey, String message) {
    String algorithm = "SHA512withRSA";
    Signature signature = null;
    String signedString = null;

    try {
        signature = Signature.getInstance(algorithm);
        signature.initSign(privateKey);
        signature.update(message.getBytes());

        byte[] signatureByteArray = signature.sign();

        signedString = "-----BEGIN SIGNATURE-----"
                + DatatypeConverter.printBase64Binary(signatureByteArray)
                + "-----END SIGNATURE-----";
    } catch(Exception e) {
        e.printStackTrace();
    }
    return signedString;    
}

可以使用java.security.Signature.verify()輕松驗證。 到目前為止,我很高興。

現在是棘手的部分:我將創建的JSON發送到另一台服務器,在這里,我的麻煩開始了:

首先,我從字符串中刪除標題和尾部(“----- BEGIN”等等......),然后,我使用base64_decode()和ASSUME,結果可以作為一個鍵使用調用openssl_pkey_get_private()

無論如何,我得到的錯誤就像

openssl_sign(): supplied key param cannot be coerced into a private key

每次我嘗試使用我的鑰匙。

所以在Java中,我創建了一個new X509EncodedKeySpec(keyBytes) ,然而,在PHP中,沒有這樣的功能(?)

我的en /解碼出錯了什么地方? 我實際上有點迷失:(

您的密鑰當前以二進制格式存儲,通常稱為“DER”格式。 這就是Java存儲密鑰的方式。 為了能夠從PHP讀取它,您必須將密鑰轉換為PEM格式,這是OpenSSL的格式。 因此,PHP要求密鑰為PEM格式。 這是一個PHP函數,它可以將DER編碼的密鑰轉換為PHP中的PEM編碼密鑰:

function X509_to_pem($der_data) {

    $BEGIN= "-----BEGIN SIGNATURE-----";
    $END = "-----BEGIN SIGNATURE-----";

    $base64Encoded= base64_encode($der_data);

    $pem = $BEGIN . "\n";
    $pem .= chunk_split($base64Encoded, 64, "\n");
    $pem .= $END . "\n";

    return $pem;
}

好吧,好像我找到了答案。 這里有一些示例代碼,結果很好用:

public class KeyTest{
static final String ALGORITHM           = "RSA";
static final int    KEYSIZE             = 1024;

static final String SIGNATURE_ALGORITHM = "SHA512withRSA";

static final String PUBLICKEY_PREFIX    = "-----BEGIN PUBLIC KEY-----";
static final String PUBLICKEY_POSTFIX   = "-----END PUBLIC KEY-----";
static final String PRIVATEKEY_PREFIX   = "-----BEGIN RSA PRIVATE KEY-----";
static final String PRIVATEKEY_POSTFIX  = "-----END RSA PRIVATE KEY-----";

public static void main(String args[]) {
    try {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEYSIZE);

        KeyPair keyPair = keyPairGenerator.genKeyPair();

        // THIS IS java.security

        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        System.out.println("Public java.security: Algorithm: " + publicKey.getAlgorithm() + "Format: " + publicKey.getFormat());
        System.out.println("Private java.security: Algorithm: " + privateKey.getAlgorithm() + "Format: " + privateKey.getFormat() + "\n");

        // THIS IS DER:

        byte[] publicKeyDER = publicKey.getEncoded();
        byte[] privateKeyDER = privateKey.getEncoded();

        System.out.println("Public DER: "+Arrays.toString(publicKeyDER));
        System.out.println("Private DER: "+Arrays.toString(privateKeyDER) + "\n");

        // THIS IS PEM:

        String publicKeyPEM = PUBLICKEY_PREFIX + "\n" + DatatypeConverter.printBase64Binary(publicKey.getEncoded()).replaceAll("(.{64})", "$1\n") + "\n" + PUBLICKEY_POSTFIX;
        String privateKeyPEM = PRIVATEKEY_PREFIX + "\n" + DatatypeConverter.printBase64Binary(privateKey.getEncoded()).replaceAll("(.{64})", "$1\n") + "\n" + PRIVATEKEY_POSTFIX;

        System.out.println("Public PEM: " + "\n"+publicKeyPEM);
        System.out.println("Private PEM: " + "\n"+privateKeyPEM + "\n");

        // Signing the teststring
        String message = "Lorem ipsum dolor sit amet";

        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initSign(privateKey);
        sig.update(message.getBytes());

        byte[] signatureByteArray = sig.sign();

        String signature = "-----BEGIN SIGNATURE-----" + "\n"
                    + DatatypeConverter.printBase64Binary(signatureByteArray).replaceAll("(.{64})", "$1\n") + "\n"
                    + "-----END SIGNATURE-----";

        System.out.println("Message Plaintext: " + message);
        System.out.println("Signature: " + "\n" + signature + "\n");
    } catch (Exception e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
}
}

這個輸出是這樣的:

Public java.security: Algorithm: RSAFormat: X.509
Private java.security: Algorithm: RSAFormat: PKCS#8

Public DER: [48, -127, -97, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -127, -115, 0, 48, -127, -119, 2, -127, -127, 0, -125, -8, 66, -86, -27, -55, 14, 50, 26, -103, -87, 102, 47, 126, -70, 57, -27, 103, -95, 10, 26, 25, -3, -18, -44, -85, 11, -19, -92, 111, 22, -6, 94, 79, -126, 32, -68, -82, -67, 24, -108, 9, 46, -100, 25, -37, 56, 2, -122, -31, -93, 56, -39, 79, -67, 33, -126, -13, -72, -120, 115, 3, -57, -120, -86, 119, 57, -110, -6, -11, -36, 109, -113, -69, -11, -81, -94, 47, 59, -7, 119, 108, -89, -26, -55, 117, -74, 125, -39, -1, 116, -116, -9, -60, -57, -78, -118, 45, 38, 120, -43, 123, -51, -104, 42, -47, 101, -120, 78, 9, -2, -84, 113, -42, -71, 101, 3, -44, -58, 39, 50, 96, 83, 90, 71, 41, 83, -13, 2, 3, 1, 0, 1]
Private DER: [48, -126, 2, 118, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 4, -126, 2, 96, 48, -126, 2, 92, 2, 1, 0, 2, -127, -127, 0, -125, -8, 66, -86, -27, -55, 14, 50, 26, -103, -87, 102, 47, 126, -70, 57, -27, 103, -95, 10, 26, 25, -3, -18, -44, -85, 11, -19, -92, 111, 22, -6, 94, 79, -126, 32, -68, -82, -67, 24, -108, 9, 46, -100, 25, -37, 56, 2, -122, -31, -93, 56, -39, 79, -67, 33, -126, -13, -72, -120, 115, 3, -57, -120, -86, 119, 57, -110, -6, -11, -36, 109, -113, -69, -11, -81, -94, 47, 59, -7, 119, 108, -89, -26, -55, 117, -74, 125, -39, -1, 116, -116, -9, -60, -57, -78, -118, 45, 38, 120, -43, 123, -51, -104, 42, -47, 101, -120, 78, 9, -2, -84, 113, -42, -71, 101, 3, -44, -58, 39, 50, 96, 83, 90, 71, 41, 83, -13, 2, 3, 1, 0, 1, 2, -127, -128, 39, -40, 45, -16, -63, 62, 9, -18, 48, -65, -46, 56, -117, 0, 125, 35, 123, -46, -28, -7, 82, -42, 36, 40, 22, -57, -87, -21, 79, 41, 71, 75, -62, 107, -55, 3, 47, 84, -90, -67, 35, -4, -3, -72, -99, -55, -27, 72, 70, 7, 28, 43, -50, -40, -41, 102, -91, -50, 6, 26, 20, 119, -64, -89, 96, 97, -101, 103, -46, 34, 95, -91, 19, 43, 4, 63, -121, 30, 85, 11, 86, 33, 58, -62, -108, 74, 56, 81, -123, 24, -8, 121, -11, -119, 43, -97, -50, 24, -60, 72, -15, 6, -87, 123, -16, 123, -17, -39, 56, -44, 97, -57, -8, 16, 9, -72, 68, 53, 1, 87, 94, -16, -54, 115, 15, -34, 93, -23, 2, 65, 0, -59, 121, -7, -34, 118, -24, 27, -9, 83, -125, -115, 120, -78, 33, -122, -78, 7, 33, 18, -44, -57, -87, 50, 99, -105, -68, -69, -82, 116, 53, -119, 113, 41, -115, 83, 66, -55, -9, -47, -12, 49, -58, 14, 68, -76, 106, 95, 102, -96, 90, -61, -40, -17, -10, 81, 116, -6, -125, -68, -33, -18, -19, 43, -11, 2, 65, 0, -85, 20, 118, 69, 108, -51, 79, -63, 70, -35, -16, -47, 81, -48, 51, 36, 99, 79, -78, -84, -86, 41, 49, -56, 101, 100, -80, 121, 53, -5, -98, -9, 53, 110, 58, -60, -39, 39, 100, -64, -108, 36, -29, -127, -13, -110, 120, 46, -31, -79, -10, -36, -26, -94, -117, -6, -76, 121, -15, -17, -31, 94, -73, 71, 2, 64, 119, 0, 35, 48, 9, 77, -92, 20, -83, -47, -9, -67, -60, -14, 105, 29, -3, 39, -44, 22, 63, 95, 89, -117, 36, -108, 74, 49, 61, -68, 73, 95, -43, 31, 98, 14, 60, 113, 71, -89, 53, 27, 89, -37, -45, 48, -54, -34, -88, 65, 42, 6, 31, -52, -70, -105, -104, -93, 44, 125, 113, -104, -96, -59, 2, 64, 122, -26, 48, 48, -97, -128, -66, -110, -78, 62, 46, 9, -79, 36, 72, 25, 19, -34, -27, 20, 117, 9, 50, -30, 43, 52, -78, 49, -31, 61, -23, 108, -35, -51, 90, 26, -97, -123, 85, 51, -93, 56, -4, -41, 22, 11, 90, -101, 19, 55, -83, -121, -13, -121, 65, -41, -48, 94, -22, 22, -47, 104, 33, 113, 2, 65, 0, -65, 101, -127, -118, 21, 122, -114, 47, 65, -96, -37, -104, 100, 52, 38, -81, 9, -9, 120, -56, -36, -92, -52, 7, -47, -8, -101, 83, -24, -82, -81, -60, 71, -47, 111, -49, 1, 46, 16, -52, -87, -79, 21, -68, 22, 18, -37, -62, 33, 102, 40, -49, -122, -98, -83, 1, 94, 29, -85, 93, -16, -7, -57, 119]

Public PEM: 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCD+EKq5ckOMhqZqWYvfro55Weh
ChoZ/e7UqwvtpG8W+l5PgiC8rr0YlAkunBnbOAKG4aM42U+9IYLzuIhzA8eIqnc5
kvr13G2Pu/Wvoi87+Xdsp+bJdbZ92f90jPfEx7KKLSZ41XvNmCrRZYhOCf6scda5
ZQPUxicyYFNaRylT8wIDAQAB
-----END PUBLIC KEY-----
Private PEM: 
-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIP4QqrlyQ4yGpmp
Zi9+ujnlZ6EKGhn97tSrC+2kbxb6Xk+CILyuvRiUCS6cGds4AobhozjZT70hgvO4
iHMDx4iqdzmS+vXcbY+79a+iLzv5d2yn5sl1tn3Z/3SM98THsootJnjVe82YKtFl
iE4J/qxx1rllA9TGJzJgU1pHKVPzAgMBAAECgYAn2C3wwT4J7jC/0jiLAH0je9Lk
+VLWJCgWx6nrTylHS8JryQMvVKa9I/z9uJ3J5UhGBxwrztjXZqXOBhoUd8CnYGGb
Z9IiX6UTKwQ/hx5VC1YhOsKUSjhRhRj4efWJK5/OGMRI8Qape/B779k41GHH+BAJ
uEQ1AVde8MpzD95d6QJBAMV5+d526Bv3U4ONeLIhhrIHIRLUx6kyY5e8u650NYlx
KY1TQsn30fQxxg5EtGpfZqBaw9jv9lF0+oO83+7tK/UCQQCrFHZFbM1PwUbd8NFR
0DMkY0+yrKopMchlZLB5Nfue9zVuOsTZJ2TAlCTjgfOSeC7hsfbc5qKL+rR58e/h
XrdHAkB3ACMwCU2kFK3R973E8mkd/SfUFj9fWYsklEoxPbxJX9UfYg48cUenNRtZ
29Mwyt6oQSoGH8y6l5ijLH1xmKDFAkB65jAwn4C+krI+LgmxJEgZE97lFHUJMuIr
NLIx4T3pbN3NWhqfhVUzozj81xYLWpsTN62H84dB19Be6hbRaCFxAkEAv2WBihV6
ji9BoNuYZDQmrwn3eMjcpMwH0fibU+iur8RH0W/PAS4QzKmxFbwWEtvCIWYoz4ae
rQFeHatd8PnHdw==
-----END RSA PRIVATE KEY-----

Message Plaintext: Lorem ipsum dolor sit amet
Signature: 
-----BEGIN SIGNATURE-----
UxhWlr8Ks3PkfaKK8IGGolUs8qjvbE4dXs8ANUtJdw48g8nk6pOEuEscpSiszc1O
fBFEG6lexRFeW4+zpyWHN8oJpVaxz7sd2lstFqu/dUkU8HtPujKkwK6c/3pzsAt8
yHru/BPRwI8Wryqm2dfiHO4cXKq5rIXfj0sSXbwI1PE=
-----END SIGNATURE-----

現在我在PHP中硬編碼這些值:

<?php

$publicKeyPEM = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCD+EKq5ckOMhqZqWYvfro55Weh
ChoZ/e7UqwvtpG8W+l5PgiC8rr0YlAkunBnbOAKG4aM42U+9IYLzuIhzA8eIqnc5
kvr13G2Pu/Wvoi87+Xdsp+bJdbZ92f90jPfEx7KKLSZ41XvNmCrRZYhOCf6scda5
ZQPUxicyYFNaRylT8wIDAQAB
-----END PUBLIC KEY-----";

$privateKeyPEM = "-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIP4QqrlyQ4yGpmp
Zi9+ujnlZ6EKGhn97tSrC+2kbxb6Xk+CILyuvRiUCS6cGds4AobhozjZT70hgvO4
iHMDx4iqdzmS+vXcbY+79a+iLzv5d2yn5sl1tn3Z/3SM98THsootJnjVe82YKtFl
iE4J/qxx1rllA9TGJzJgU1pHKVPzAgMBAAECgYAn2C3wwT4J7jC/0jiLAH0je9Lk
+VLWJCgWx6nrTylHS8JryQMvVKa9I/z9uJ3J5UhGBxwrztjXZqXOBhoUd8CnYGGb
Z9IiX6UTKwQ/hx5VC1YhOsKUSjhRhRj4efWJK5/OGMRI8Qape/B779k41GHH+BAJ
uEQ1AVde8MpzD95d6QJBAMV5+d526Bv3U4ONeLIhhrIHIRLUx6kyY5e8u650NYlx
KY1TQsn30fQxxg5EtGpfZqBaw9jv9lF0+oO83+7tK/UCQQCrFHZFbM1PwUbd8NFR
0DMkY0+yrKopMchlZLB5Nfue9zVuOsTZJ2TAlCTjgfOSeC7hsfbc5qKL+rR58e/h
XrdHAkB3ACMwCU2kFK3R973E8mkd/SfUFj9fWYsklEoxPbxJX9UfYg48cUenNRtZ
29Mwyt6oQSoGH8y6l5ijLH1xmKDFAkB65jAwn4C+krI+LgmxJEgZE97lFHUJMuIr
NLIx4T3pbN3NWhqfhVUzozj81xYLWpsTN62H84dB19Be6hbRaCFxAkEAv2WBihV6
ji9BoNuYZDQmrwn3eMjcpMwH0fibU+iur8RH0W/PAS4QzKmxFbwWEtvCIWYoz4ae
rQFeHatd8PnHdw==
-----END RSA PRIVATE KEY-----";

$message_plaintext = "Lorem ipsum dolor sit amet";

$signature = "-----BEGIN SIGNATURE-----
UxhWlr8Ks3PkfaKK8IGGolUs8qjvbE4dXs8ANUtJdw48g8nk6pOEuEscpSiszc1O
fBFEG6lexRFeW4+zpyWHN8oJpVaxz7sd2lstFqu/dUkU8HtPujKkwK6c/3pzsAt8
yHru/BPRwI8Wryqm2dfiHO4cXKq5rIXfj0sSXbwI1PE=
-----END SIGNATURE-----";

function verify_signature($message, $public_key, $signature) {
    $algorithm = OPENSSL_ALGO_SHA512;
    $hash_algorithm = 'sha512';

    $signature = str_replace('-----BEGIN SIGNATURE-----', '', $signature);
    $signature = str_replace('-----END SIGNATURE-----', '', $signature);
    $signature = base64_decode($signature);
    $success = openssl_verify($message, $signature, $public_key,    $algorithm);
    return $success;
}

var_dump(verify_signature($message_plaintext, $publicKeyPEM, $signature));

?>

......這實際上有效。 我仍然不明白為什么傑克的解決方案不起作用,但是哦......

希望這有助於其他人管理密鑰,因為我沒有在網上找到太多的跨平台示例...

我推薦的一個網站是http://pumka.net/2009/12/19/reading-writing-and-converting-rsa-keys-in-pem-der-publickeyblob-and-privatekeyblob-formats/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM