You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
11 KiB
302 lines
11 KiB
import sun.misc.BASE64Decoder; |
|
import sun.misc.BASE64Encoder; |
|
|
|
import javax.crypto.BadPaddingException; |
|
import javax.crypto.Cipher; |
|
import javax.crypto.IllegalBlockSizeException; |
|
import java.io.IOException; |
|
import java.io.UnsupportedEncodingException; |
|
import java.lang.reflect.Array; |
|
import java.security.Key; |
|
import java.security.KeyFactory; |
|
import java.security.PrivateKey; |
|
import java.security.PublicKey; |
|
import java.security.spec.PKCS8EncodedKeySpec; |
|
import java.security.spec.X509EncodedKeySpec; |
|
import java.util.HashMap; |
|
import java.util.Map; |
|
import java.util.regex.Matcher; |
|
import java.util.regex.Pattern; |
|
|
|
/** |
|
* @author richie |
|
* @version 10.0 |
|
* Created by richie on 2019-07-08 |
|
*/ |
|
public class Password { |
|
|
|
private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj0yc/l+39O1XukrG1cA4rmJEDlmfdUZHVWFrFkYA3XvZI9FQIYjx/irVurCtXsgn88xWlvEMAlKQVdU5EDvv5qS+9X83LV6tyShFQ4hVa+s1n+eHhWj3PTTTsELN7SEmaCdzFNAcfXYE+c51mvWSioOktORZ4l9Sh3sQ+b/Gir70hJk+ARI2pE2xmEZQCC1vks8rSaay/LuGE+PBkuK42qbcfWkBhvXb8GqnW2+3A61hFa8VSdZmEq5qqDvCUSBxjVhATgAO57qQof3v13lyn8zk+Fg/KYeT1iuxgpVqYjLARyr2f1hZBiiZT5yNtwVVk3+4uP2AyIh+oNAOujNSawIDAQAB"; |
|
|
|
private static final String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCPTJz+X7f07Ve6SsbVwDiuYkQOWZ91RkdVYWsWRgDde9kj0VAhiPH+KtW6sK1eyCfzzFaW8QwCUpBV1TkQO+/mpL71fzctXq3JKEVDiFVr6zWf54eFaPc9NNOwQs3tISZoJ3MU0Bx9dgT5znWa9ZKKg6S05FniX1KHexD5v8aKvvSEmT4BEjakTbGYRlAILW+SzytJprL8u4YT48GS4rjaptx9aQGG9dvwaqdbb7cDrWEVrxVJ1mYSrmqoO8JRIHGNWEBOAA7nupCh/e/XeXKfzOT4WD8ph5PWK7GClWpiMsBHKvZ/WFkGKJlPnI23BVWTf7i4/YDIiH6g0A66M1JrAgMBAAECggEAJ8Xt9TSADH0r0ksa8Q0PLmeb2BfMCHLfLbWCUYZQiyjq1eQsx4IJGLCu7chH9ny7ihF3HyH8YVClOw2ZbwYTygKD9gO/Ptp+hcylnN7kRrXcBmvu03qU1Ooqr0t7eIuw60u3x1kT70aojuVdAwuSBtwPBR40TH6Em5Hu3kL6SlvU3F9EBDycH1OsonqOaS3z0F7EdFv7NqYKM1VsvhnkfximTE8ikhxdN4vSko9alJii2wM94Hca3NOI6Ug8IkjNr44qj4jVucYzvEw6d0tcWkQRh22dD2617Yeym0tsx+JxMPvMEcOqF3+VRDqb+xFmRrwTh5z0QU96n8r5NcBasQKBgQDv/0ni1SA7EZ3tDesfHSD0dIYk5U6OESzNwWSlmf13Gu7pg71B439O4VIU5OpGrtuA75xHPE6HcwBoEpQjGCYSMerWNhiwPJbXS/CdJVld8ZiIHDu40xCH96EB7y+yG+wueh0HDk/SjwRAcuL58LJnVVje9SSMK3kgeuYrubjkhwKBgQCY2rUMB0KtEisxv/z/YfAfYbCfqp9AGgLYDZjc7cvqczniv7k4AdP0DSOh4eBPe+1whXahhyQ8zkIKZeaYhCV3awXqQJ0D1BhNlMPKnDNzfGfueRnmcji1goiLcuMApqm+33oebPSnv1D6X88M+05S3husJH+lWM51/8eW0zH//QKBgDShY26fFmZdwqhNuRYlqShytUg6ETQOiCjHFG9Mic0o1uPWxBZC8ZQ2zW1PliDSD8kCwt7MVtxVV+16xYm8rfynfbxkOJ3Na7bjLG0J18NGTBDtQBuUDbgDkgd+kJMalHzMwrjdZpviSShpCWWOZ1FJ4idi0xT6I6H/0aIdJHLZAoGBAIOk4QZx/lfGbRMU0ZU1STQN06s/rJXtkQN4em3UE6phALqr+p4k3OG0qzqRqblq9yzQlUI6fNgtn60K5BX4wbfeoaKFcXVJpoCyngmSi7FrtKsq+0aAmxygRm8rTBxUbZ8pIyivF+qdF+X6u/znNyahid2xNYo3OOFhoAji7Y4VAoGBAOXoMHEE1rQsRQEr0p7BFVGTsSwfFCzbiACA5BmQ/fMas2z4lc44MZYqsVHAqqRqbonF+pK2c+6RHqhVpCPC6NTTlqispcP5OTTW2mSj3JFiyTWxkep3m8JiSrJX/uLQcGJHFomPTznHmYLinNlQXm6Z19zkUFIWxvP/QY5SIzKX"; |
|
|
|
private static final String PUBLIC_KEY_MARK = "public"; |
|
private static final String PRIVATE_KEY_MARK = "private"; |
|
|
|
private static final Pattern PUBLIC_PATTERN = Pattern.compile("-----BEGIN PUBLIC KEY-----([\\s\\S]*?)-----END PUBLIC KEY-----"); |
|
private static final Pattern PRIVATE_PATTERN = Pattern.compile("-----BEGIN PRIVATE KEY-----([\\s\\S]*?)-----END PRIVATE KEY-----"); |
|
|
|
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; |
|
|
|
private static final int FRAGMENT_LENGTH = 245; |
|
private static final int FRAGMENT_LENGTH_DECRYPT = 256; |
|
|
|
private String secretKeyText; |
|
|
|
public Password() { |
|
this(""); |
|
} |
|
|
|
public Password(String secretKeyText) { |
|
this.secretKeyText = secretKeyText; |
|
} |
|
|
|
public String getPublicKey() { |
|
return getKey(PUBLIC_KEY_MARK, PUBLIC_KEY); |
|
} |
|
|
|
public String getPrivateKey() { |
|
return getKey(PRIVATE_KEY_MARK, PRIVATE_KEY); |
|
} |
|
|
|
public void setSecretKeyText(String secretKeyText) { |
|
this.secretKeyText = secretKeyText; |
|
} |
|
|
|
private String getKey(String type, String defaultValue) { |
|
Map<String, String> map = getKeyPair(); |
|
if (map == null) { |
|
return defaultValue; |
|
} |
|
String value = map.get(type); |
|
if (value == null) { |
|
return defaultValue; |
|
} |
|
return value; |
|
} |
|
|
|
private Map<String, String> getKeyPair() { |
|
if (secretKeyText == null || "".equals(secretKeyText)) { |
|
return null; |
|
} |
|
|
|
HashMap<String, String> map = new HashMap<>(); |
|
|
|
map.put(PUBLIC_KEY_MARK, findMatchedText(secretKeyText, PUBLIC_PATTERN)); |
|
map.put(PRIVATE_KEY_MARK, findMatchedText(secretKeyText, PRIVATE_PATTERN)); |
|
return map; |
|
} |
|
|
|
private String findMatchedText(String text, Pattern pattern) { |
|
Matcher m = pattern.matcher(text); |
|
if (m.find()) { |
|
return m.group(1).trim(); |
|
} |
|
return ""; |
|
} |
|
|
|
/** |
|
* RSA加密 |
|
*/ |
|
public String encrypt(String plainText) { |
|
return encrypt(plainText, string2PublicKey(getPublicKey())); |
|
} |
|
|
|
/** |
|
* RSA加密 |
|
* |
|
* @param plainText 要加密的文本内容 |
|
* @param publicKey 用于加密的公钥 |
|
* @return 加密后的内容 |
|
*/ |
|
public String encrypt(String plainText, Key publicKey) { |
|
if (plainText == null || "".equals(plainText)) { |
|
return plainText; |
|
} |
|
try { |
|
byte[] publicEncrypt = encrypt(plainText.getBytes("utf-8"), publicKey); |
|
return byte2Base64(publicEncrypt); |
|
} catch (UnsupportedEncodingException e) { |
|
throw new RuntimeException(e); |
|
} |
|
} |
|
|
|
/** |
|
* RSA加密 |
|
* |
|
* @param plainTextData 要加密的内容 |
|
* @param publicKey 用于加密的公钥 |
|
* @return 加密后的内容 |
|
*/ |
|
private byte[] encrypt(byte[] plainTextData, Key publicKey) { |
|
|
|
if (isEmpty(plainTextData)) { |
|
return plainTextData; |
|
} |
|
try { |
|
Cipher c1 = Cipher.getInstance("RSA"); |
|
c1.init(Cipher.ENCRYPT_MODE, publicKey); |
|
return dealEncryptFragment(plainTextData, c1); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
return null; |
|
} |
|
|
|
public String decrypt(String cipherText) { |
|
return decrypt(cipherText, string2PrivateKey(getPrivateKey())); |
|
} |
|
|
|
/** |
|
* RSA解密 |
|
* |
|
* @param cipherText 密文数据 |
|
* @return 解密后的内容 |
|
*/ |
|
public String decrypt(String cipherText, Key privateKey) { |
|
|
|
if (cipherText == null || "".equals(cipherText)) { |
|
return cipherText; |
|
} |
|
byte[] bytes = null; |
|
try { |
|
bytes = decrypt(base642Byte(cipherText), privateKey); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
if (bytes == null) { |
|
return null; |
|
} |
|
try { |
|
return new String(bytes, "utf-8"); |
|
} catch (UnsupportedEncodingException e) { |
|
throw new RuntimeException(e); |
|
} |
|
} |
|
|
|
/** |
|
* RSA解密 |
|
* |
|
* @param cipherData 密文数据 |
|
* @param privateKey 用于解密的私钥 |
|
* @return 解密后的内容 |
|
*/ |
|
private byte[] decrypt(byte[] cipherData, Key privateKey) { |
|
try { |
|
Cipher c1 = Cipher.getInstance("RSA"); |
|
c1.init(Cipher.DECRYPT_MODE, privateKey); |
|
return dealDecryptFragment(cipherData, c1); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
return null; |
|
} |
|
|
|
|
|
private PublicKey string2PublicKey(String pubStr) { |
|
try { |
|
byte[] keyBytes = base642Byte(pubStr); |
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); |
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); |
|
return keyFactory.generatePublic(keySpec); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
return null; |
|
} |
|
|
|
private PrivateKey string2PrivateKey(String priStr) { |
|
try { |
|
byte[] keyBytes = base642Byte(priStr); |
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); |
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); |
|
return keyFactory.generatePrivate(keySpec); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
return null; |
|
} |
|
|
|
private byte[] base642Byte(String base64Key) throws IOException { |
|
BASE64Decoder decoder = new BASE64Decoder(); |
|
return decoder.decodeBuffer(base64Key); |
|
} |
|
|
|
private String byte2Base64(byte[] bytes) { |
|
BASE64Encoder encoder = new BASE64Encoder(); |
|
return encoder.encode(bytes); |
|
} |
|
|
|
private byte[] dealEncryptFragment(byte[] data, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException { |
|
|
|
byte[] result = new byte[]{}; |
|
int i; |
|
for (i = 0; i < data.length; i += FRAGMENT_LENGTH) { |
|
byte[] fragment = subarray(data, i, i + FRAGMENT_LENGTH); |
|
byte[] update = cipher.doFinal(fragment); |
|
result = addAll(result, update); |
|
} |
|
return result; |
|
} |
|
|
|
private byte[] dealDecryptFragment(byte[] data, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException { |
|
|
|
byte[] result = new byte[]{}; |
|
int i; |
|
for (i = 0; i < data.length; i += FRAGMENT_LENGTH_DECRYPT) { |
|
byte[] fragment = subarray(data, i, i + FRAGMENT_LENGTH_DECRYPT); |
|
byte[] update = cipher.doFinal(fragment); |
|
result = addAll(result, update); |
|
} |
|
return result; |
|
} |
|
|
|
public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) { |
|
if (array == null) { |
|
return null; |
|
} |
|
if (startIndexInclusive < 0) { |
|
startIndexInclusive = 0; |
|
} |
|
if (endIndexExclusive > array.length) { |
|
endIndexExclusive = array.length; |
|
} |
|
final int newSize = endIndexExclusive - startIndexInclusive; |
|
if (newSize <= 0) { |
|
return EMPTY_BYTE_ARRAY; |
|
} |
|
|
|
final byte[] subarray = new byte[newSize]; |
|
System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); |
|
return subarray; |
|
} |
|
|
|
public static byte[] addAll(final byte[] array1, final byte... array2) { |
|
if (array1 == null) { |
|
return clone(array2); |
|
} else if (array2 == null) { |
|
return clone(array1); |
|
} |
|
final byte[] joinedArray = new byte[array1.length + array2.length]; |
|
System.arraycopy(array1, 0, joinedArray, 0, array1.length); |
|
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); |
|
return joinedArray; |
|
} |
|
|
|
public static byte[] clone(final byte[] array) { |
|
if (array == null) { |
|
return null; |
|
} |
|
return array.clone(); |
|
} |
|
|
|
public static boolean isEmpty(final byte[] array) { |
|
return getLength(array) == 0; |
|
} |
|
|
|
public static int getLength(final Object array) { |
|
if (array == null) { |
|
return 0; |
|
} |
|
return Array.getLength(array); |
|
} |
|
}
|
|
|