这个程序有相当大的问题,由于这个实验要交了,就没有往下做,交了个有问题的程序上去,要做的事是这样的:先构造一个64的全0的二进制字符串,然后用加盐后的密码作为密钥对这个数据块进行DES加密,将加密计算出的结果保存,将用户名,盐值,结果保存,然后用户验证的时候,先看用户存在不,存在的话就取相应的盐值和用户输入的密码用相同的方式加密,将结果与保存的结果比较,相同的话就验证成功。

然后自己没有用过什么密钥空间,什么密钥构造的类什么的,都是看的文档,自己摸索着用的那些方法,所以应该使用方式不太对,然后就是编码的时候,可能对什么字符,字节,之类的概念混乱,导致编码后总是不能得到以前的盐值,然后就会抛出异常,说Salt只能是8字节的……反正每次都提示这个错,而且都是在用户验证时,到输入密码后抛出的异常,有次很偶然居然顺利验证成功了,就截图写报告了,还有就是验证时取盐值输出时,后面有一大段空白……如果各位有时间能亲自运行下就能理解我的意思了……我强行加了substring(0,5),我不太明白默认的编码后的字符解码后怎么不一样了……

class PBECoder:口令管理信息的生成

class Base64:实现位串变换。

class Agen:实现用户注册,将用户名,盐值和加密后的信息保存在passwd.txt文本文件中
class Test:实验用户口令验证,从passwd.txt中取出用户名,与输入比较,如果存在,则提示用户未注册,若用户存在,则取出相应的盐值,然后提示输入密码,将输入密码与相应的盐值生成加密后的信息,与passwd.txt中保存的信息比较,如果相同则验证通过,如果不相同,则验证未通过。
注释部分为程序设计过程中用于测试结果的中间输出
class PBECoder:主要完成加密的操作
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public abstract class PBECoder
{
              public static final String ALGORITHM="PBEWITHMD5andDES";
              public static final int ITERATION_COUNT=25;
                private static Key toKey(String password)throws Exception
                     {
                            PBEKeySpec  keySpec=
new PBEKeySpec(password.toCharArray());//带有一个密码的构造方法,导出一个密钥
                            SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(ALGORITHM);//返回转换DES的秘密密钥工厂
                            SecretKey secretKey=keyFactory.generateSecret(keySpec);//密钥材料生成SecretKey对象
                            return secretKey;
                     }
                     public static byte[] encrypt(String password,byte[] salt)//加密算法
                            throws Exception{
                            Key key=toKey(password);
                            byte[] data={0,0,0,0,0,0,0,0,
                                 0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0};
                            PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);//基于密码的加密法构造一个参数集合
Cipher cipher=Cipher.getInstance(ALGORITHM);//返回实现DESCipher 对象cipher.init(Cipher.ENCRYPT_MODE,key,paramSpec);//用密钥和一组算法参数初始化此 Cipher
                            return cipher.doFinal(data);
                     }//加密数据
                    public static byte[] returnsalt(String password,byte[] salt)
                                throws Exception{
                                Key key=toKey(password);
                            byte[] data={0,0,0,0,0,0,0,0,
                                 0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0,
                                   0,0,0,0,0,0,0,0};
                            PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);//基于密码的加密法构造一个参数集合
                                return paramSpec.getSalt();
     }
}
---------------------------------------------------------------------------------------------------------------------
class Base64:主要完成字符串与字节的转换:(用的网上找的代码)
import java.io.UnsupportedEncodingException;
public class Base64 {
    private static char[] base64EncodeChars = new char[] {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
        'w', 'x', 'y', 'z', '0', '1', '2', '3',
        '4', '5', '6', '7', '8', '9', '+', '/' };
    private byte []Array=new byte[10000];
    private byte []dArray=new byte[10000];
    private byte []d1Array=new byte[10000];
    private char []decode=new char[10000];
    private int length=0;
    public String encode(String str) throws UnsupportedEncodingException                //编码
    {
        StringBuffer buf=new StringBuffer();
        int sign=0;
        int b1,b2,b3;
        Array=str.getBytes();
        length=Array.length;
        sign=length/3;
        int j=0;
        for(int i=0;i<sign;i++)
        {
            b1=Array[j++]&0xff;
            b2=Array[j++]&0xff;
            b3=Array[j++]&0xff;
            buf.append(base64EncodeChars[b1>>>2]);
            buf.append(base64EncodeChars[((b1&0x3)<<4|(b2&0xf0)>>>4)]);
          buf.append(base64EncodeChars[((b2&0x0f)<<2)|((b3&0xc0)>>>6)]);
            buf.append(base64EncodeChars[b3&0x3f]);
         }
        sign=length%3;
        if(sign==0)
            return buf.toString();
        else if(sign==1)
        {
            b1=Array[j]&0xff;
            buf.append(base64EncodeChars[b1>>>2]);
            buf.append(base64EncodeChars[(b1&0x3)<<4]);
            buf.append("==");
            return buf.toString();
        }
        else
        {
            b1=Array[j]&0xff;
            b2=Array[j+1]&0xff;
            buf.append(base64EncodeChars[b1>>>2]);
         buf.append(base64EncodeChars[(((b1&0x3)<<4)|((b2&0xf0)>>>4))]);
            buf.append(base64EncodeChars[(b2&0x0f)<<2]);
            buf.append("=");
            return buf.toString();
        }
    }
    public String decode(String str) throws UnsupportedEncodingException                //解码
    {
        int k=0;
            int b1,b2,b3,b4;
            decode=str.toCharArray();
             for(int i=0;i<decode.length;i++)
            {
                if(decode[i]!=-1)
                dArray[i]=Search(decode[i]);
                else
                   break;
           }
           int flag;
           int j=0;
            flag=decode.length/4;
             for(int i=0;i<flag-1;i++)
            {
                 b1=dArray[j++];
                 b2=dArray[j++];
                 b3=dArray[j++];
                 b4=dArray[j++];
                 d1Array[k++]=(byte)((b1<<2)|((b2&0x30)>>>4));
             d1Array[k++]=(byte)((b2<<4)|((b3&0x3c)>>>2));
                d1Array[k++]=(byte)((b3<<6)|b4);
           }
            if(dArray.length%4==0)
          {
              b1=dArray[j++];
              b2=dArray[j++];
               b3=dArray[j++];
                 b4=dArray[j++];
               d1Array[k++]=(byte)((b1<<2)|((b2&0x30)>>>4));
                 d1Array[k++]=(byte)((b2<<4)|((b3&0x3c)>>>2));
                 d1Array[k++]=(byte)((b3<<6)|b4);
            }
             else if(dArray.length%4==2)
                b1=dArray[j];
                d1Array[k]=(byte)(b1<<2);
            }
            else
            {
                  b1=dArray[j++];
                b2=dArray[j++];
                b3=dArray[j];
                d1Array[k++]=(byte)((b1<<2)|((b2&0x30)>>>4));
                d1Array[k]=(byte)((b2<<4)|((b3&0x3c)>>>2));
            }
            String tr=new String(d1Array);
            return tr.toString();
    }
    public byte Search(char a)
    {
        byte i;
        if(a=='=')
            return -1;
        for(i=0;i<64;i++)
        {
            if(base64EncodeChars[i]==a)
                break;
        }
        return i;
    }
 }
---------------------------------------------------------------------------------------------------------------------
class Agen:主要实现用户注册,生成用户信息文本
import java.io.*;
import java.security.SecureRandom;
public class Agen
{
       public static byte[] initSalt()throws Exception
       {
              SecureRandom random=new SecureRandom();//构造一个实现默认随机数算法的安全随机数生成器 (RNG)
               return random.generateSeed(8);//返回给定的种子字节数量
       }
       public Agen(){}
       public static void main(String[] args)throws Exception
       {
              System.out.println("注册新用户");
              System.out.println("输入用户名");
              BufferedReader Username=
new BufferedReader(new InputStreamReader(System.in));
              String username=Username.readLine();
              System.out.println("输入密码");
              BufferedReader Passwd=
new BufferedReader(new InputStreamReader(System.in));
                Agen agen=new Agen();
                byte[] Salt=agen.initSalt()
                String Salt2=new String(Salt);
                /*System.out.println(Salt2);*/ 
                Base64 base64=new Base64();
              String passwd=Passwd.readLine();
                /*System.out.println(passwd);
                System.out.println(base64.encode(Salt2));
                String sAL=base64.decode(base64.encode(Salt2));
                System.out.println(sAL);*/
                byte[] data=PBECoder.encrypt(passwd,Salt);
                FileOutputStream fileout=new FileOutputStream(new File("E:/passwd.txt"));
       fileout.write((username+":"+base64.encode(Salt2)+":"+base64.encode(new String(data))).getBytes());
       }
}
---------------------------------------------------------------------------------------------------------------------
class Test:实现从txt中分离出用户名,盐值和生成的口令信息,进行身份验证
import java.io.*;
import java.security.SecureRandom;
public class Test
{     
       public static void main(String[] args)throws Exception
       {
              System.out.println("用户登陆");
              System.out.println("输入用户名");
              BufferedReader Username
=new BufferedReader(new InputStreamReader(System.in));
              String username=Username.readLine();
              BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream(new File("E:/passwd.txt"))));
              String save=in.readLine();
              int userpos=save.indexOf(":");
              String USER=save.substring(0,userpos);
              boolean b1=USER.equals(username);
              if(!b1)
                     System.out.println("用户未注册");
              else
              {
                     System.out.println("请输入密码");
                     BufferedReader Passwd
=new BufferedReader(new InputStreamReader(System.in));
                     String passwd=Passwd.readLine();
                     int saltpos=save.indexOf(":",userpos+1);
                     Base64 base64=new Base64();
                        String Sa=save.substring(userpos+1,saltpos);
                        /*System.out.println(Sa);
                        System.out.println(userpos);
                        System.out.println(saltpos);
                        System.out.println(Sa+Sa.length());*/
                        byte[] sal=Sa.getBytes();
                        /*System.out.println(sal);*/
                     String salt=base64.decode(Sa).substring(0,5);//这个不知道怎么弄。。。不是取6位吧……
                        /*System.out.println(salt);*/
                        byte[] SAL=salt.getBytes();
                        /*System.out.println(SAL);*/
                        byte[] data=PBECoder.encrypt(passwd,SAL);
                     String re=base64.encode(new String(data));
                        /*System.out.println(re);*/
                     int pwdpos=save.indexOf(":",saltpos);
                     String PWD=save.substring(saltpos+1,save.length());
                     boolean b2=re.equals(PWD);
                     if(!b2)
                            System.out.println("密码不正确");
                     else
                            System.out.println("验证成功");
              }
       }
}                                           
 首先在运行窗口依次编译PEBCoder.java,Agen.java,Test.java
编译成功后先运行Agen.class,进行用户注册,运行命令为java Agen,然后根据提示输入用户名和密码;
然后在制定目录下生成了passwd.txt,然后在运行窗口下运行Test.class,进行用户验证,运行命令为java Test,然后根据提示输入用户名,如果用户名已经注册了,则提示输入密码,如果密码输入正确则验证成功;如果用户名没有注册则提示用户未注册。
以下是对各种情况的实验结果:
 验证成功:
以下为生成的用户信息文件:
 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_加盐

 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_JAVA_02

以下是输出中间结果对程序的分析:(验证成功的情况)
用户注册信息:
 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_加密_03

你看那个Base64编码后的盐值下面那个就与上面那个不一样,多了个?,然后就不能还原到最初那个数组,其实那个-108,88,-119……我不知道用什么方式把它当做可打印的存进txt然后取出后还原……
与passwd.txt文件中保存的信息对比盐值,盐值正确保存:
 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_口令_04

验证用户信息:
 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_JAVA_05

重新生成的口令信息与文件中保存的文件信息一致,验证成功
本次项目的功能实现还有不完善的地方,目前只写了一个用户的身份验证,不过多用户的添加只需在写入文件的时候在文件末尾添加,只是要重新考虑从文件中分离用户名,盐值,口令信息的方法,此外,由于是第一次使用JAVA中一些基于口令的密钥空间和密钥工厂的方法,使用上可能存在不正确的地方,导致有的时候用户验证的时候出现错误
 

Java写的一个用户口令加密,验证(有问题,自己解决不了)_加盐_06