【发布时间】:2015-11-04 02:31:43
【问题描述】:
我们必须使用需要随机生成盐的 HMAC-SHA256 加密我们的数据。我们以这种方式生成盐:
public String generateSalt() throws Exception
{
KeyGenerator keyGen;
String salt = null;
try
{
keyGen = KeyGenerator.getInstance( "HmacSHA256" );
keyGen.init( 128 );
SecretKey key = keyGen.generateKey();
byte[] encodedKey = key.getEncoded();
salt = Base64.encodeBase64String( key.getEncoded() );
LOG.info( "Salt : " + salt );
}
catch ( NoSuchAlgorithmException )
{
e.printStackTrace();
throw e;
}
return salt;
}
根据我们的测试,这个盐生成部分是正确的。我对下一部分有疑问:
现在我必须将这个盐以二进制格式写入一个文件(比如命名为 pie_raw),这样做是:
private void writeToFile( byte[] saltBytes, String fileName ) throws FileNotFoundException, IOException
{
DataOutputStream out = new DataOutputStream( new FileOutputStream( enviro.getOutputFilePath()
+ fileName ) );
out.write( saltBytes );
out.close();
LOG.info( " Raw file created : " + enviro.getOutputFilePath() + fileName );
}
然后,我必须使用“.pem”中提供的公共 RSA 密钥加密这个盐,对于 Java 实现,密码将是“RSA/ECB/OAEPWithSHA1AndMGF1Padding”。最后二进制密文应该被写入一个名为“pie_key”的文件中。这部分是这样实现的:
private byte[] encryptSalt( String salt ) throws Exception
{
byte[] cipheredKey = null;
try
{
String keyString= readKeyFile( enviro.getPublicKeyFile() );
byte[] pem = pemToDer(keyString);
PublicKey publicKey = derToPublicKey(pem);
//PublicKey publicKey = getPublicKey( enviro.getPublicKeyFile() );
// Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
rsaCipher.init( Cipher.ENCRYPT_MODE, publicKey );
cipheredKey = rsaCipher.doFinal( salt.getBytes( "UTF-8" ) );//"UTF-8"
LOG.info( "Cyphered key : " + cipheredKey.toString() );
}
catch ( IOException | GeneralSecurityException e )
{
e.printStackTrace();
throw e;
}
return cipheredKey;
}
static String readKeyFile( String path )
throws IOException
{
String line = null;
try (BufferedReader br =
new BufferedReader( new FileReader( path ) ))
{
StringBuilder sb = new StringBuilder();
line = br.readLine();
while ( line != null )
{
sb.append( line );
sb.append( "\n" );
line = br.readLine();
}
return sb.toString();
}
}
public static byte[] pemToDer( String pemKey ) throws GeneralSecurityException
{
String[] parts = pemKey.split( "-----" );
return DatatypeConverter.parseBase64Binary( parts[ parts.length / 2 ] );
}
public static PublicKey derToPublicKey( byte[] asn1key ) throws GeneralSecurityException
{
X509EncodedKeySpec spec = new X509EncodedKeySpec( asn1key );
KeyFactory keyFactory = KeyFactory.getInstance( "RSA" );
return keyFactory.generatePublic( spec );
}
通过调用上面的“writeToFile”方法,将此加密的盐以二进制格式写入名为“pie_key”的文件中。
现在“pie_key”文件的内容应该与 cmd 的输出相匹配:
openssl rsautl -encrypt -pubin -inkey wrap_pie_key_rsa.pem -oaep -in pie_key.raw -out pie_key
但是无论我尝试什么(您可能会发现一些方法的迹象,我尝试过)都没有工作,这意味着最终的二进制加密盐与 openssl cmd 的输出不匹配。
知道我做错了什么吗?
我正在使用 Java 7。.pem(部分)看起来像
-----BEGIN PUBLIC KEY-----
MIIBIjANBgk345iG9w0BAQEFAA54328AMIIBCgKCAQEAt4GLJGPmvYdxwwAe59n3
.
.
.
.
7QIDNQAB
-----END PUBLIC KEY-----
提前致谢。
【问题讨论】:
-
输出无法匹配,因为填充是随机的。只能通过一个加密一个解密来判断是否兼容。
-
您需要钥匙还是盐? HMAC 不将盐作为输入参数。 什么 OpenSSL 命令?
标签: java encryption cryptography public-key-encryption public-key