公钥处理Java / PHP

氙石

目前,我陷入了RSA密钥管理的问题。具体来说,我想在Java中创建一个RSA密钥对,对某些内容(即字符串)进行签名,然后将公钥,签名和签名后的字符串导出到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();
}

将密钥导出到字符串(将最终在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中,没有此类功能(?)

我的编码/解码哪里出问题了?我实际上有点迷路了:(

氙石

好吧,好像我找到了答案。下面是一些示例代码,结果证明工作正常:

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/

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章