1.现在后台生成密钥对,把得到公钥的加密系数,加密指数,传个前台登录界面,进行加密
//rsa生成密钥对,和加密解密函数。
public class RSAUtil
{
private static String RSAKeyStore = "RSAKey.txt"
public static KeyPair generateKeyPair()
throws Exception
{
try
{
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
new BouncyCastleProvider());
int KEY_SIZE = 1024;
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
System.out.println(keyPair.getPrivate().toString().length());
System.out.println(keyPair.getPublic());
saveKeyPair(keyPair);
return keyPair;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
public static KeyPair getKeyPair() throws Exception {
FileInputStream fis = new FileInputStream(Constants_core.ContextRealPath + File.separator + RSAKeyStore);
ObjectInputStream oos = new ObjectInputStream(fis);
KeyPair kp = (KeyPair)oos.readObject();
oos.close();
fis.close();
return kp;
}
public static void saveKeyPair(KeyPair kp) throws Exception
{
FileOutputStream fos = new FileOutputStream(Constants_core.ContextRealPath + File.separator + RSAKeyStore);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(kp);
oos.close();
fos.close();
}
public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent)
throws Exception
{
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA",
new BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
new BigInteger(modulus), new BigInteger(publicExponent));
try {
return (RSAPublicKey)keyFac.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent)
throws Exception
{
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA",
new BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
new BigInteger(modulus), new BigInteger(privateExponent));
try {
return (RSAPrivateKey)keyFac.generatePrivate(priKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
public static byte[] encrypt(PublicKey pk, byte[] data)
throws Exception
{
try
{
Cipher cipher = Cipher.getInstance("RSA",
new BouncyCastleProvider());
cipher.init(1, pk);
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(data.length);
int leavedSize = data.length % blockSize;
int blocksSize = (leavedSize != 0) ? data.length / blockSize + 1 :
data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i *
outputSize);
else {
cipher.doFinal(data, i * blockSize, data.length - i *
blockSize, raw, i * outputSize);
}
++i;
}
return raw;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
public static byte[] decrypt(PrivateKey pk, byte[] raw)
throws Exception
{
try
{
Cipher cipher = Cipher.getInstance("RSA",
new BouncyCastleProvider());
cipher.init(2, pk);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
++j;
}
return bout.toByteArray();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
public static String decrypt(PrivateKey pk, String str_en)
throws Exception
{
String str_mw = "";
byte[] en_result = new BigInteger(str_en, 16).toByteArray();
byte[] de_result = decrypt(getKeyPair().getPrivate(), en_result);
StringBuffer sb = new StringBuffer();
sb.append(new String(de_result));
str_mw = sb.reverse().toString();
str_mw = URLDecoder.decode(str_mw, "UTF-8");
return str_mw;
}
public static void main(String[] args)
throws Exception
{
Constants_core.ContextRealPath = "D:/EPS/ygpt/WebRoot";
String test = "hello world";
byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
String stren = Base64.encode(en_test);
byte[] de_test = decrypt(getKeyPair().getPrivate(), Base64.decode(stren));
System.out.println(new String(de_test));
}
}
//前台js加密
var j_password = document.getElementById("j_password_show").value;
document.getElementById("j_password").value = encryptedString(key, encodeURIComponent(j_password));
LOGIN_FORM.submit();
2.点击登录时,密码被用rsa加密后发到spring security的 DaoAuthenticationProvider 进行密码校验处理,
在密码发到后台后,先用在第一步时产生的私钥进行解密,解密后再用spring security 提供的 passwordEncoder类的
this.passwordEncoder.isPasswordValid()方法来进行,密码校验。
public DaoAuthenticationProvider()
{
setPasswordEncoder(new PlaintextPasswordEncoder());
}
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException
{
Object salt = null;
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
this.logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
//rsa私钥解密
try {
presentedPassword = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),presentedPassword);
} catch (Exception e) {
this.logger.error(e, e.fillInStackTrace());
}
String presentedPassword = authentication.getCredentials().toString();
//校验密码
if (!this.passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
this.logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
}
protected void doAfterPropertiesSet() throws Exception
{
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
}
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException
{
UserDetails loadedUser;
try
{
loadedUser = getUserDetailsService().loadUserByUsername(username);
} catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString();
this.passwordEncoder.isPasswordValid(this.userNotFoundEncodedPassword, presentedPassword, null);
}
throw notFound;
} catch (Exception repositoryProblem) {
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
}
if (loadedUser == null) {
throw new AuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
}
return loadedUser;
}
public void setPasswordEncoder(Object passwordEncoder)
{
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
if (passwordEncoder instanceof org.springframework.security.authentication.encoding.PasswordEncoder) {
setPasswordEncoder((org.springframework.security.authentication.encoding.PasswordEncoder)passwordEncoder);
return;
}
if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) {
org.springframework.security.crypto.password.PasswordEncoder delegate = (org.springframework.security.crypto.password.PasswordEncoder)passwordEncoder;
setPasswordEncoder(new org.springframework.security.authentication.encoding.PasswordEncoder(delegate) {
public String encodePassword(String rawPass, Object salt) {
checkSalt(salt);
return this.val$delegate.encode(rawPass);
}
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
checkSalt(salt);
return this.val$delegate.matches(rawPass, encPass);
}
private void checkSalt(Object salt) {
Assert.isNull(salt, "Salt value must be null when used with crypto module PasswordEncoder");
}
});
return;
}
throw new IllegalArgumentException("passwordEncoder must be a PasswordEncoder instance");
}
private void setPasswordEncoder(org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder) {
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
this.userNotFoundEncodedPassword = passwordEncoder.encodePassword("userNotFoundPassword", null);
this.passwordEncoder = passwordEncoder;
}
protected org.springframework.security.authentication.encoding.PasswordEncoder getPasswordEncoder() {
return this.passwordEncoder;
}
public void setSaltSource(SaltSource saltSource)
{
this.saltSource = saltSource;
}
protected SaltSource getSaltSource() {
return this.saltSource;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
protected UserDetailsService getUserDetailsService() {
return this.userDetailsService;
}
}
3.为什么这么做呢,因为,后台数据库存储的密码都是经过不可逆算法加密过的,用这个方法,对3第三部解密后的密码在进行加密处理,最后和数据存储的加密密码进行比较,返回true则密码通过验证。