当前位置: 首页 > 面试题库 >

将字符串转换为加密密钥,反之亦然

魏元白
2023-03-14
问题内容

我目前正在研究一种将键转换为字符串,反之亦然的方法。它适用于公钥转换,并将私钥转换为String。由于某些原因,同一代码不会将String转换回私钥,我只是无法弄清楚。

转换器代码为:

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

@SuppressWarnings("restriction")
public  class KeyConvert {


public static PublicKey stringToPublicKey(String s) {

    BASE64Decoder decoder = new BASE64Decoder();

    byte[] c = null;
    KeyFactory keyFact = null;
    PublicKey returnKey = null;

    try {
        c = decoder.decodeBuffer(s);
        keyFact = KeyFactory.getInstance("DSA", "SUN");
    } catch (Exception e) {
        System.out.println("Error in Keygen");
        e.printStackTrace();
    }


    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(c);
    try {
        returnKey = keyFact.generatePublic(x509KeySpec);
    } catch (Exception e) {

        System.out.println("Error in Keygen2");
        e.printStackTrace();

    }

    return returnKey;

}
public static PrivateKey stringToPrivateKey(String s) {

    BASE64Decoder decoder = new BASE64Decoder();
    byte[] c = null;
    KeyFactory keyFact = null;
    PrivateKey returnKey = null;

    try {

                    c = decoder.decodeBuffer(s);
        keyFact = KeyFactory.getInstance("DSA", "SUN");
    } catch (Exception e) {

        System.out.println("Error in first try catch of stringToPrivateKey");
        e.printStackTrace();
    }


    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(c);
    try {   //the next line causes the crash
        returnKey = keyFact.generatePrivate(x509KeySpec);
    } catch (Exception e) {

        System.out.println("Error in stringToPrivateKey");
        e.printStackTrace();
    }

    return returnKey;

}

public static String publicKeyToString(PublicKey p) {

    byte[] publicKeyBytes = p.getEncoded();
    BASE64Encoder encoder = new BASE64Encoder();
    return encoder.encode(publicKeyBytes);

}
public static String privateKeyToString(PrivateKey p) {

    byte[] privateKeyBytes = p.getEncoded();
    BASE64Encoder encoder = new BASE64Encoder();
    return encoder.encode(privateKeyBytes);
}
}

我正在使用的驱动程序代码是:

import java.security.PrivateKey;
import java.security.PublicKey;

public class SQLServerTest {
public static void main(String[] args) throws Exception {


    ServerSQLManager s = new ServerSQLManager();
    ServerUser user = new ServerUser("testUser", "pass123");
    s.getKeys(user);


    PublicKey testKey = user.getPublicKey();
    System.out.println(testKey);
    PrivateKey testKey2 = user.getPrivateKey();
    System.out.println(testKey2);
}
}

运行此命令时,我得到了不合适的密钥说明,有人可以为此指出正确的方向吗?控制台输出为:

Error in stringToPrivateKey


java.security.spec.InvalidKeySpecException: Inappropriate key specification
at sun.security.provider.DSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at KeyConvert.stringToPrivateKey(KeyConvert.java:61)
at ServerSQLManager.getKeys(ServerSQLManager.java:128)
at SQLServerTest.main(SQLServerTest.java:20)

Sun DSA Public Key
     Parameters:DSA
    p:     fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669
    455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7
    6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb
    83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7
q:     9760508f 15230bcc b292b982 a2eb840b f0581cf5
g:     f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267
    5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1
    3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b
    cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a

    y:
    5210e849 24d90208 56802887 dfaededf 78d3e6d0 d2e59a1c fb52dde8 96147784
    b2589365 2529414c 8265b61d c1fe6d98 cee0eea3 cce1e366 cd621ca7 41e3a94f
    9c15bfcb eb860d19 21efd574 79bb5b15 8159b1cb e3fc7f76 f85a6fc1 8d65afc6
    7c4fafda 503b01b5 99752ee4 2408ad80 1d983579 b00e2120 6d735874 ccaea1c0

null

我知道我不应该使用sun.misc。*库,我们正在研究Apache版本,但仍然想弄清楚(也永远不会是生产代码)

任何建议表示赞赏。


问题答案:

公用密钥可以使用X509EncodedKeySpec进行存储,而私钥则使用PKCS8EncodedKeySpec。例如这样:

public static PrivateKey loadPrivateKey(String key64) throws GeneralSecurityException {
    byte[] clear = base64Decode(key64);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
    KeyFactory fact = KeyFactory.getInstance("DSA");
    PrivateKey priv = fact.generatePrivate(keySpec);
    Arrays.fill(clear, (byte) 0);
    return priv;
}


public static PublicKey loadPublicKey(String stored) throws GeneralSecurityException {
    byte[] data = base64Decode(stored);
    X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
    KeyFactory fact = KeyFactory.getInstance("DSA");
    return fact.generatePublic(spec);
}

public static String savePrivateKey(PrivateKey priv) throws GeneralSecurityException {
    KeyFactory fact = KeyFactory.getInstance("DSA");
    PKCS8EncodedKeySpec spec = fact.getKeySpec(priv,
            PKCS8EncodedKeySpec.class);
    byte[] packed = spec.getEncoded();
    String key64 = base64Encode(packed);

    Arrays.fill(packed, (byte) 0);
    return key64;
}


public static String savePublicKey(PublicKey publ) throws GeneralSecurityException {
    KeyFactory fact = KeyFactory.getInstance("DSA");
    X509EncodedKeySpec spec = fact.getKeySpec(publ,
            X509EncodedKeySpec.class);
    return base64Encode(spec.getEncoded());
}


public static void main(String[] args) throws Exception {
    KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA");
    KeyPair pair = gen.generateKeyPair();

    String pubKey = savePublicKey(pair.getPublic());
    PublicKey pubSaved = loadPublicKey(pubKey);
    System.out.println(pair.getPublic()+"\n"+pubSaved);

    String privKey = savePrivateKey(pair.getPrivate());
    PrivateKey privSaved = loadPrivateKey(privKey);
    System.out.println(pair.getPrivate()+"\n"+privSaved);
}


 类似资料:
  • 问题内容: 我正在生成密钥,需要将其存储在数据库中,因此我将其转换为字符串,但是要从字符串中获取密钥。有哪些可能的方法可以做到这一点? 我的代码是 如何从字符串取回密钥? 问题答案: 您可以将转换为字节数组(),然后Base64将其编码为。要转换回a ,Base64 会对String进行解码,并在a中使用它来重建您的原始字符串。 对于Java 8 字符串的SecretKey: 字符串到Secret

  • 下面是一个生成IV并将其转换为Base64字符串的示例... 但是,当我将IV的字符串表示形式传递到加密方法中,然后将其转换回字节数组时,下面的代码会失败,说明IV的大小不正确。 在字节数组和字符串表示之间有没有一种标准的转换加密密钥和IV的方法?

  • 问题内容: 我将如何使用python将IP地址转换为十进制数字,反之亦然? 例如,对于,我想使用易于存储在数据库中的十进制或二进制形式,然后检索它。 问题答案: 将IP字符串转换为长整数: 另一种方式:

  • 问题内容: 有没有办法将netty ByteBuf转换为String,反之亦然? 问题答案: 您可以使用转换为字符串。 您可以使用和转换为ByteBuf。

  • 我有以下字符串格式的RSA私钥。 我正在尝试使用下面的代码片段将其转换为PrivateKey类型- 我正在犯错误- 它给我一个错误的生成私人方法。 尝试在这里使用Java的答案:将DKIM私钥从RSA转换为用于JavaMail的DER

  • 问题内容: 我必须在Android中将字节数组转换为字符串,但是我的字节数组包含负值。 如果我再次将该字符串转换为字节数组,则得到的值与原始字节数组值不同。 我该怎么做才能正确转换?我用于执行转换的代码如下: 我陷入了这个问题。 问题答案: 你的字节数组必须具有某种编码。如果你使用负值,则编码不能为ASCII。一旦弄清楚了,就可以使用以下方法将一组字节转换为字符串: 你可以使用许多编码,请查看Su