import javax.xml.bind.DatatypeConverter ;
import java.net.URLDecoder ;
import java.net.URLEncoder ;
import java.util.Date ;
import java.text.SimpleDateFormat ;
import javax.crypto.spec.IvParameterSpec ;
import javax.crypto.spec.PBEKeySpec ;
import javax.crypto.spec.SecretKeySpec ;
import javax.crypto.Cipher ;
import javax.crypto.SecretKey ;
import javax.crypto.SecretKeyFactory ;
import java.security.Key ;
public class EncryptString {
public static void main
( String [ ] args
) { if ( args.length == 4 ) {
String cyphertext
= EncryptString.
encryptWithPassword ( args
[ 0 ] ,args
[ 1 ] ,args
[ 2 ] ,args
[ 3 ] ) ; System .
out .
println ( "encryptWithPassword(password=" + args
[ 0 ] + ",salt=" + args
[ 1 ] + ",IV=" + args
[ 2 ] + ",plaintext=" + args
[ 3 ] + ") => " + cyphertext
) ; String plaintext
= EncryptString.
decryptWithPassword ( args
[ 0 ] ,args
[ 1 ] ,args
[ 2 ] ,cyphertext
) ; System .
out .
println ( "decryptWithPassword(password=" + args
[ 0 ] + ",salt=" + args
[ 1 ] + ",iv=" + args
[ 2 ] + ",cyphertext=" + cyphertext
+ ") => [" + plaintext
+ "]" ) ; }
else if ( args.length == 3 ) {
String cyphertext
= EncryptString.
encryptWithKey ( args
[ 0 ] ,args
[ 1 ] ,args
[ 2 ] ) ; System .
out .
println ( "encryptWithKey(key=" + args
[ 0 ] + ",IV=" + args
[ 1 ] + ",plaintext=" + args
[ 2 ] + ") => " + cyphertext
) ; System .
out .
println ( "cyphertext=" + DatatypeConverter.
printHexBinary ( DatatypeConverter.
parseBase64Binary ( cyphertext
) ) ) ; String plaintext
= EncryptString.
decryptWithKey ( args
[ 0 ] ,args
[ 1 ] ,cyphertext
) ; System .
out .
println ( "decryptWithKey(key=" + args
[ 0 ] + ",iv=" + args
[ 1 ] + ",cyphertext=" + cyphertext
+ ") => [" + plaintext
+ "]" ) ; }
else {
System .
err .
println ( "usage: java EncryptString { key | password salt} IV plaintext" ) ; }
}
byte [ ] buffer = null ;
try {
secretKeySpec= null ;
PBEKeySpec pbeKeySpec = new PBEKeySpec( password.toCharArray ( ) ,DatatypeConverter.parseHexBinary ( salt) ,1000 ,128 ) ;
SecretKeyFactory secretKeyFactory= SecretKeyFactory.getInstance ( "PBKDF2WithHmacSHA1" ) ;
//SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey secretKey= secretKeyFactory.generateSecret ( pbeKeySpec) ;
SecretKeySpec secretKeySpec= new SecretKeySpec( secretKey.getEncoded ( ) ,"AES" ) ;
System .
out .
println ( "secretKeySpec.getEncoded()=" + DatatypeConverter.
printHexBinary ( secretKeySpec.
getEncoded ( ) ) + " secretKeySpec.getAlgorithm()=" + secretKeySpec.
getAlgorithm ( ) ) ; byte [ ] ivBytes = DatatypeConverter.parseHexBinary ( iv) ;
IvParameterSpec ivSpec = new IvParameterSpec( ivBytes) ;
Cipher cipher = javax.crypto .Cipher .getInstance ( "AES/CBC/PKCS5Padding" ) ;
cipher.init ( Cipher.ENCRYPT_MODE , secretKeySpec, ivSpec) ;
buffer = cipher.doFinal ( plaintext.getBytes ( ) ) ;
System .
out .
println ( "plaintext.length()=" + plaintext.
length ( ) + " buffer.length=" + buffer.
length ) ; cipherText= DatatypeConverter.printBase64Binary ( buffer) ;
}
System .
err .
println ( e.
getMessage ( ) ) ; e.printStackTrace ( ) ;
}
return cipherText;
}
try {
byte [ ] buffer = DatatypeConverter.parseBase64Binary ( cyphertext) ;
System .
out .
println ( "buffer.length=" + buffer.
length ) ; PBEKeySpec pbeKeySpec = new PBEKeySpec( password.toCharArray ( ) ,DatatypeConverter.parseHexBinary ( salt) ,1000 ,128 ) ;
SecretKeyFactory secretKeyFactory= SecretKeyFactory.getInstance ( "PBKDF2WithHmacSHA1" ) ;
//SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey secretKey= secretKeyFactory.generateSecret ( pbeKeySpec) ;
SecretKeySpec secretKeySpec= new SecretKeySpec( secretKey.getEncoded ( ) ,"AES" ) ;
byte [ ] ivBytes = DatatypeConverter.parseHexBinary ( iv) ;
IvParameterSpec ivSpec = new IvParameterSpec( ivBytes) ;
Cipher cipher = javax.crypto .Cipher .getInstance ( "AES/CBC/PKCS5Padding" ) ;
cipher.init ( Cipher.DECRYPT_MODE , secretKeySpec,ivSpec) ;
plainText
= new String ( cipher.
doFinal ( buffer
) ) ; }
System .
err .
println ( e.
getMessage ( ) ) ; e.printStackTrace ( ) ;
}
return plainText;
}
byte [ ] buffer = null ;
try {
SecretKeySpec aesKeySpec = new SecretKeySpec( DatatypeConverter.parseHexBinary ( key) ,"AES" ) ;
byte [ ] ivBytes = DatatypeConverter.parseHexBinary ( iv) ;
IvParameterSpec ivSpec = new IvParameterSpec( ivBytes) ;
Cipher cipher = javax.crypto .Cipher .getInstance ( "AES/CBC/PKCS5Padding" ) ;
cipher.init ( Cipher.ENCRYPT_MODE , aesKeySpec, ivSpec) ;
buffer = cipher.doFinal ( plaintext.getBytes ( ) ) ;
System .
out .
println ( "plaintext.length()=" + plaintext.
length ( ) + " buffer.length=" + buffer.
length ) ; cipherText= DatatypeConverter.printBase64Binary ( buffer) ;
}
System .
err .
println ( e.
getMessage ( ) ) ; e.printStackTrace ( ) ;
}
return cipherText;
}
try {
byte [ ] buffer = DatatypeConverter.parseBase64Binary ( cyphertext) ;
System .
out .
println ( "buffer.length=" + buffer.
length ) ; SecretKeySpec aesKeySpec = new SecretKeySpec( DatatypeConverter.parseHexBinary ( key) ,"AES" ) ;
byte [ ] ivBytes = DatatypeConverter.parseHexBinary ( iv) ;
IvParameterSpec ivSpec = new IvParameterSpec( ivBytes) ;
Cipher cipher = javax.crypto .Cipher .getInstance ( "AES/CBC/PKCS5Padding" ) ;
cipher.init ( Cipher.DECRYPT_MODE , aesKeySpec,ivSpec) ;
plainText
= new String ( cipher.
doFinal ( buffer
) ) ; }
System .
err .
println ( e.
getMessage ( ) ) ; e.printStackTrace ( ) ;
}
return plainText;
}
}
aW1wb3J0IGphdmF4LnhtbC5iaW5kLkRhdGF0eXBlQ29udmVydGVyOwppbXBvcnQgamF2YS5uZXQuVVJMRGVjb2RlcjsKaW1wb3J0IGphdmEubmV0LlVSTEVuY29kZXI7CmltcG9ydCBqYXZhLnV0aWwuRGF0ZTsKaW1wb3J0IGphdmEudGV4dC5TaW1wbGVEYXRlRm9ybWF0OwoKaW1wb3J0IGphdmF4LmNyeXB0by5zcGVjLkl2UGFyYW1ldGVyU3BlYzsKaW1wb3J0IGphdmF4LmNyeXB0by5zcGVjLlBCRUtleVNwZWM7CmltcG9ydCBqYXZheC5jcnlwdG8uc3BlYy5TZWNyZXRLZXlTcGVjOwppbXBvcnQgamF2YXguY3J5cHRvLkNpcGhlcjsKaW1wb3J0IGphdmF4LmNyeXB0by5TZWNyZXRLZXk7CmltcG9ydCBqYXZheC5jcnlwdG8uU2VjcmV0S2V5RmFjdG9yeTsKaW1wb3J0IGphdmEuc2VjdXJpdHkuS2V5OwoKcHVibGljIGNsYXNzIEVuY3J5cHRTdHJpbmcgewogIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKICAgIGlmKGFyZ3MubGVuZ3RoID09IDQpewogICAgICAgIFN0cmluZyBjeXBoZXJ0ZXh0PUVuY3J5cHRTdHJpbmcuZW5jcnlwdFdpdGhQYXNzd29yZChhcmdzWzBdLGFyZ3NbMV0sYXJnc1syXSxhcmdzWzNdKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImVuY3J5cHRXaXRoUGFzc3dvcmQocGFzc3dvcmQ9IithcmdzWzBdKyIsc2FsdD0iK2FyZ3NbMV0rIixJVj0iK2FyZ3NbMl0rIixwbGFpbnRleHQ9IithcmdzWzNdKyIpID0+ICIrY3lwaGVydGV4dCk7CiAgICAgICAgU3RyaW5nIHBsYWludGV4dD1FbmNyeXB0U3RyaW5nLmRlY3J5cHRXaXRoUGFzc3dvcmQoYXJnc1swXSxhcmdzWzFdLGFyZ3NbMl0sY3lwaGVydGV4dCk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJkZWNyeXB0V2l0aFBhc3N3b3JkKHBhc3N3b3JkPSIrYXJnc1swXSsiLHNhbHQ9IithcmdzWzFdKyIsaXY9IithcmdzWzJdKyIsY3lwaGVydGV4dD0iK2N5cGhlcnRleHQrIikgPT4gWyIrcGxhaW50ZXh0KyJdIik7CiAgICB9CiAgICBlbHNlIGlmKGFyZ3MubGVuZ3RoID09IDMpewogICAgICAgIFN0cmluZyBjeXBoZXJ0ZXh0PUVuY3J5cHRTdHJpbmcuZW5jcnlwdFdpdGhLZXkoYXJnc1swXSxhcmdzWzFdLGFyZ3NbMl0pOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiZW5jcnlwdFdpdGhLZXkoa2V5PSIrYXJnc1swXSsiLElWPSIrYXJnc1sxXSsiLHBsYWludGV4dD0iK2FyZ3NbMl0rIikgPT4gIitjeXBoZXJ0ZXh0KTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImN5cGhlcnRleHQ9IitEYXRhdHlwZUNvbnZlcnRlci5wcmludEhleEJpbmFyeShEYXRhdHlwZUNvbnZlcnRlci5wYXJzZUJhc2U2NEJpbmFyeShjeXBoZXJ0ZXh0KSkpOwogICAgICAgIFN0cmluZyBwbGFpbnRleHQ9RW5jcnlwdFN0cmluZy5kZWNyeXB0V2l0aEtleShhcmdzWzBdLGFyZ3NbMV0sY3lwaGVydGV4dCk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJkZWNyeXB0V2l0aEtleShrZXk9IithcmdzWzBdKyIsaXY9IithcmdzWzFdKyIsY3lwaGVydGV4dD0iK2N5cGhlcnRleHQrIikgPT4gWyIrcGxhaW50ZXh0KyJdIik7CiAgICB9CiAgICBlbHNlewogICAgICAgIFN5c3RlbS5lcnIucHJpbnRsbigidXNhZ2U6IGphdmEgRW5jcnlwdFN0cmluZyB7IGtleSB8IHBhc3N3b3JkIHNhbHR9IElWIHBsYWludGV4dCIpOwogICAgfQogIH0KCgogIHB1YmxpYyBzdGF0aWMgU3RyaW5nIGVuY3J5cHRXaXRoUGFzc3dvcmQoU3RyaW5nIHBhc3N3b3JkLCBTdHJpbmcgc2FsdCwgU3RyaW5nIGl2LCBTdHJpbmcgcGxhaW50ZXh0KXsKICAgICBTdHJpbmcgY2lwaGVyVGV4dD1udWxsOwogICAgIGJ5dGVbXSBidWZmZXIgPSBudWxsOwogICAgIHRyeXsKICAgICAgICAgc2VjcmV0S2V5U3BlYz1udWxsOwogICAgICAgICBQQkVLZXlTcGVjIHBiZUtleVNwZWMgPSBuZXcgUEJFS2V5U3BlYyhwYXNzd29yZC50b0NoYXJBcnJheSgpLERhdGF0eXBlQ29udmVydGVyLnBhcnNlSGV4QmluYXJ5KHNhbHQpLDEwMDAsMTI4KTsKICAgICAgICAgU2VjcmV0S2V5RmFjdG9yeSBzZWNyZXRLZXlGYWN0b3J5PVNlY3JldEtleUZhY3RvcnkuZ2V0SW5zdGFuY2UoIlBCS0RGMldpdGhIbWFjU0hBMSIpOwogICAgICAgICAvL1NlY3JldEtleUZhY3Rvcnkgc2VjcmV0S2V5RmFjdG9yeT1TZWNyZXRLZXlGYWN0b3J5LmdldEluc3RhbmNlKCJQQkVXaXRoTUQ1QW5kREVTIik7CiAgICAgICAgIFNlY3JldEtleSBzZWNyZXRLZXk9c2VjcmV0S2V5RmFjdG9yeS5nZW5lcmF0ZVNlY3JldChwYmVLZXlTcGVjKTsKICAgICAgICAgU2VjcmV0S2V5U3BlYyBzZWNyZXRLZXlTcGVjPW5ldyBTZWNyZXRLZXlTcGVjKHNlY3JldEtleS5nZXRFbmNvZGVkKCksIkFFUyIpOwogICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInNlY3JldEtleVNwZWMuZ2V0RW5jb2RlZCgpPSIrRGF0YXR5cGVDb252ZXJ0ZXIucHJpbnRIZXhCaW5hcnkoc2VjcmV0S2V5U3BlYy5nZXRFbmNvZGVkKCkpKyIgIHNlY3JldEtleVNwZWMuZ2V0QWxnb3JpdGhtKCk9IitzZWNyZXRLZXlTcGVjLmdldEFsZ29yaXRobSgpKTsKICAgICAgICAgYnl0ZVtdIGl2Qnl0ZXMgPSBEYXRhdHlwZUNvbnZlcnRlci5wYXJzZUhleEJpbmFyeShpdik7CiAgICAgICAgIEl2UGFyYW1ldGVyU3BlYyBpdlNwZWMgPSBuZXcgSXZQYXJhbWV0ZXJTcGVjKGl2Qnl0ZXMpOwogICAgICAgICBDaXBoZXIgY2lwaGVyID0gamF2YXguY3J5cHRvLkNpcGhlci5nZXRJbnN0YW5jZSgiQUVTL0NCQy9QS0NTNVBhZGRpbmciKTsKICAgICAgICAgY2lwaGVyLmluaXQoQ2lwaGVyLkVOQ1JZUFRfTU9ERSwgc2VjcmV0S2V5U3BlYywgaXZTcGVjKTsKICAgICAgICAgYnVmZmVyID0gY2lwaGVyLmRvRmluYWwocGxhaW50ZXh0LmdldEJ5dGVzKCkpOwogICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oInBsYWludGV4dC5sZW5ndGgoKT0iK3BsYWludGV4dC5sZW5ndGgoKSsiIGJ1ZmZlci5sZW5ndGg9IitidWZmZXIubGVuZ3RoKTsKICAgICAgICAgY2lwaGVyVGV4dD1EYXRhdHlwZUNvbnZlcnRlci5wcmludEJhc2U2NEJpbmFyeShidWZmZXIpOwogICAgIH0KICAgICBjYXRjaCAoRXhjZXB0aW9uIGUpewogICAgICAgIFN5c3RlbS5lcnIucHJpbnRsbihlLmdldE1lc3NhZ2UoKSk7CiAgICAgICAgZS5wcmludFN0YWNrVHJhY2UoKTsKICAgICB9CiAgICAgcmV0dXJuIGNpcGhlclRleHQ7CiAgfQoKICBwdWJsaWMgc3RhdGljIFN0cmluZyBkZWNyeXB0V2l0aFBhc3N3b3JkKFN0cmluZyBwYXNzd29yZCwgU3RyaW5nIHNhbHQsIFN0cmluZyBpdiwgU3RyaW5nIGN5cGhlcnRleHQpewogICAgIFN0cmluZyBwbGFpblRleHQgPSBudWxsOwogICAgIHRyeXsKICAgICAgICAgYnl0ZVtdIGJ1ZmZlciA9IERhdGF0eXBlQ29udmVydGVyLnBhcnNlQmFzZTY0QmluYXJ5KGN5cGhlcnRleHQpOwogICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oImJ1ZmZlci5sZW5ndGg9IitidWZmZXIubGVuZ3RoKTsKICAgICAgICAgUEJFS2V5U3BlYyBwYmVLZXlTcGVjID0gbmV3IFBCRUtleVNwZWMocGFzc3dvcmQudG9DaGFyQXJyYXkoKSxEYXRhdHlwZUNvbnZlcnRlci5wYXJzZUhleEJpbmFyeShzYWx0KSwxMDAwLDEyOCk7CiAgICAgICAgIFNlY3JldEtleUZhY3Rvcnkgc2VjcmV0S2V5RmFjdG9yeT1TZWNyZXRLZXlGYWN0b3J5LmdldEluc3RhbmNlKCJQQktERjJXaXRoSG1hY1NIQTEiKTsKICAgICAgICAgLy9TZWNyZXRLZXlGYWN0b3J5IHNlY3JldEtleUZhY3Rvcnk9U2VjcmV0S2V5RmFjdG9yeS5nZXRJbnN0YW5jZSgiUEJFV2l0aE1ENUFuZERFUyIpOwogICAgICAgIFNlY3JldEtleSBzZWNyZXRLZXk9c2VjcmV0S2V5RmFjdG9yeS5nZW5lcmF0ZVNlY3JldChwYmVLZXlTcGVjKTsKICAgICAgICAgU2VjcmV0S2V5U3BlYyBzZWNyZXRLZXlTcGVjPW5ldyBTZWNyZXRLZXlTcGVjKHNlY3JldEtleS5nZXRFbmNvZGVkKCksIkFFUyIpOwogICAgICAgICBieXRlW10gaXZCeXRlcyA9IERhdGF0eXBlQ29udmVydGVyLnBhcnNlSGV4QmluYXJ5KGl2KTsKICAgICAgICAgSXZQYXJhbWV0ZXJTcGVjIGl2U3BlYyA9IG5ldyBJdlBhcmFtZXRlclNwZWMoaXZCeXRlcyk7CiAgICAgICAgIENpcGhlciBjaXBoZXIgPSBqYXZheC5jcnlwdG8uQ2lwaGVyLmdldEluc3RhbmNlKCJBRVMvQ0JDL1BLQ1M1UGFkZGluZyIpOwogICAgICAgICBjaXBoZXIuaW5pdChDaXBoZXIuREVDUllQVF9NT0RFLCBzZWNyZXRLZXlTcGVjLGl2U3BlYyk7CiAgICAgICAgIHBsYWluVGV4dCA9IG5ldyBTdHJpbmcoY2lwaGVyLmRvRmluYWwoYnVmZmVyKSk7CiAgICAgfQogICAgIGNhdGNoIChFeGNlcHRpb24gZSl7CiAgICAgICAgU3lzdGVtLmVyci5wcmludGxuKGUuZ2V0TWVzc2FnZSgpKTsKICAgICAgICBlLnByaW50U3RhY2tUcmFjZSgpOwogICAgIH0KICAgICByZXR1cm4gcGxhaW5UZXh0OwogIH0KCiAgcHVibGljIHN0YXRpYyBTdHJpbmcgZW5jcnlwdFdpdGhLZXkoU3RyaW5nIGtleSwgU3RyaW5nIGl2LCBTdHJpbmcgcGxhaW50ZXh0KXsKICAgICBTdHJpbmcgY2lwaGVyVGV4dD1udWxsOwogICAgIGJ5dGVbXSBidWZmZXIgPSBudWxsOwogICAgIHRyeXsKICAgICAgICAgU2VjcmV0S2V5U3BlYyBhZXNLZXlTcGVjID0gbmV3IFNlY3JldEtleVNwZWMoRGF0YXR5cGVDb252ZXJ0ZXIucGFyc2VIZXhCaW5hcnkoa2V5KSwiQUVTIik7CiAgICAgICAgIGJ5dGVbXSBpdkJ5dGVzID0gRGF0YXR5cGVDb252ZXJ0ZXIucGFyc2VIZXhCaW5hcnkoaXYpOwogICAgICAgICBJdlBhcmFtZXRlclNwZWMgaXZTcGVjID0gbmV3IEl2UGFyYW1ldGVyU3BlYyhpdkJ5dGVzKTsKICAgICAgICAgQ2lwaGVyIGNpcGhlciA9IGphdmF4LmNyeXB0by5DaXBoZXIuZ2V0SW5zdGFuY2UoIkFFUy9DQkMvUEtDUzVQYWRkaW5nIik7CiAgICAgICAgIGNpcGhlci5pbml0KENpcGhlci5FTkNSWVBUX01PREUsIGFlc0tleVNwZWMsIGl2U3BlYyk7CiAgICAgICAgIGJ1ZmZlciA9IGNpcGhlci5kb0ZpbmFsKHBsYWludGV4dC5nZXRCeXRlcygpKTsKICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJwbGFpbnRleHQubGVuZ3RoKCk9IitwbGFpbnRleHQubGVuZ3RoKCkrIiBidWZmZXIubGVuZ3RoPSIrYnVmZmVyLmxlbmd0aCk7CiAgICAgICAgIGNpcGhlclRleHQ9RGF0YXR5cGVDb252ZXJ0ZXIucHJpbnRCYXNlNjRCaW5hcnkoYnVmZmVyKTsKICAgICB9CiAgICAgY2F0Y2ggKEV4Y2VwdGlvbiBlKXsKICAgICAgICBTeXN0ZW0uZXJyLnByaW50bG4oZS5nZXRNZXNzYWdlKCkpOwogICAgICAgIGUucHJpbnRTdGFja1RyYWNlKCk7CiAgICAgfQogICAgIHJldHVybiBjaXBoZXJUZXh0OwogIH0KCiAgcHVibGljIHN0YXRpYyBTdHJpbmcgZGVjcnlwdFdpdGhLZXkoU3RyaW5nIGtleSwgU3RyaW5nIGl2LCBTdHJpbmcgY3lwaGVydGV4dCl7CiAgICAgU3RyaW5nIHBsYWluVGV4dCA9IG51bGw7CiAgICAgdHJ5ewogICAgICAgICBieXRlW10gYnVmZmVyID0gRGF0YXR5cGVDb252ZXJ0ZXIucGFyc2VCYXNlNjRCaW5hcnkoY3lwaGVydGV4dCk7CiAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiYnVmZmVyLmxlbmd0aD0iK2J1ZmZlci5sZW5ndGgpOwogICAgICAgICBTZWNyZXRLZXlTcGVjIGFlc0tleVNwZWMgPSBuZXcgU2VjcmV0S2V5U3BlYyhEYXRhdHlwZUNvbnZlcnRlci5wYXJzZUhleEJpbmFyeShrZXkpLCJBRVMiKTsKICAgICAgICAgYnl0ZVtdIGl2Qnl0ZXMgPSBEYXRhdHlwZUNvbnZlcnRlci5wYXJzZUhleEJpbmFyeShpdik7CiAgICAgICAgIEl2UGFyYW1ldGVyU3BlYyBpdlNwZWMgPSBuZXcgSXZQYXJhbWV0ZXJTcGVjKGl2Qnl0ZXMpOwogICAgICAgICBDaXBoZXIgY2lwaGVyID0gamF2YXguY3J5cHRvLkNpcGhlci5nZXRJbnN0YW5jZSgiQUVTL0NCQy9QS0NTNVBhZGRpbmciKTsKICAgICAgICAgY2lwaGVyLmluaXQoQ2lwaGVyLkRFQ1JZUFRfTU9ERSwgYWVzS2V5U3BlYyxpdlNwZWMpOwogICAgICAgICBwbGFpblRleHQgPSBuZXcgU3RyaW5nKGNpcGhlci5kb0ZpbmFsKGJ1ZmZlcikpOwogICAgIH0KICAgICBjYXRjaCAoRXhjZXB0aW9uIGUpewogICAgICAgIFN5c3RlbS5lcnIucHJpbnRsbihlLmdldE1lc3NhZ2UoKSk7CiAgICAgICAgZS5wcmludFN0YWNrVHJhY2UoKTsKICAgICB9CiAgICAgcmV0dXJuIHBsYWluVGV4dDsKICB9Cgp9