package hamaster.gradesign.mgr;
import hamaster.gradesgin.ibe.IBEConstraints;
import hamaster.gradesgin.ibe.io.SecureByteArrayInputStream;
import hamaster.gradesgin.ibe.io.SecureByteArrayOutputStream;
import hamaster.gradesgin.util.Hash;
import hamaster.gradesign.IBECSR;
import hamaster.gradesign.IdentityDescription;
import hamaster.gradesign.daemon.EJBClient;
import hamaster.gradesign.dao.IDRequestDAO;
import hamaster.gradesign.dao.UserDAO;
import hamaster.gradesign.entity.IDRequest;
import hamaster.gradesign.entity.IdentityDescriptionEntity;
import hamaster.gradesign.entity.User;
import hamaster.gradesign.ibe.util.Hex;
import hamaster.gradesign.idmgmt.IBESystemBean;
import hamaster.gradesign.idmgmt.IdentityDescriptionBean;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientManager {
/**
* 操作成功完成
*/
public final static int ERR_SUCCESS = 0;
/**
* 未知操作
*/
public final static int ERR_UNKNOWN_OP = 1;
/**
* 处理请求过程中发生异常
*/
public final static int ERR_PROC_REQ = 2;
/**
* 数据缺失
*/
public final static int ERR_EOF = 3;
/**
* 错误的用户名/密码
*/
public final static int ERR_WRONG_PWD = 4;
/**
* 错误的ID访问密码
*/
public final static int ERR_WRONG_ID_PWD = 5;
/**
* 用户试图获取他人身份描述
*/
public final static int ERR_ID_THEFT = 6;
/**
* ID已经被人使用
*/
public final static int ERR_ID_USED = 7;
/**
* 注册所用的电子邮件地址已被使用
*/
public final static int ERR_EMAIL_USED = 8;
/**
* 数据错误
*/
public final static int ERR_DATA_ERROR = 9;
//////////////////////////////////////////////////////////////////////////////
/**
* 用户等未被激活
*/
public final static int ERR_NOT_ACTIVE = 10;
private IdentityDescriptionBean identityDescriptionBean;
private UserDAO userDAO;
private IDRequestDAO idRequestDAO;
private IBESystemBean systemBean;
private Logger logger;
public ClientManager() {
logger = LoggerFactory.getLogger(getClass());
}
/**
* 获取用户身份描述信息
* @param request 请求体 具体内容:<ul><li>
* 用户注册时电子邮件地址(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 密码(长度信息1字节 数据最多255字节)</li><li>
* 要请求的ID(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 用户为要请求的ID所设置的访问密码(长度信息1字节 数据最多255字节)</li><ul>
* @return <pre>如果操作成功 返回用户身份描述信息(采用用户设置的密码加密后的结果)
* 包含一字节的成功代码和数字节的身份描述信息内容
* 如果操作失败 返回包含错误码的长度一字节的数组</pre>
* 操作成功返回的内容:<ul><li>
* 操作结果 1字节</li><li>
* 参数g 128字节</li><li>
* 参数g1 128字节</li><li>
* 参数h 128字节</li><li>
* 椭圆函数参数(长度4字节 内容数字节)</li><li>
* 私钥rID 20字节</li><li>
* 私钥hID 128字节</li><li>
* 数字签名公共参数(长度不定)</li><li>
* 签名主密钥 20字节</li><li>
* 证书有效期开始 8字节</li><li>
* 证书有效期 8字节</li><li>
* 所有者字符串长度(长度4字节 内容数字节)</li><li>
* 根证书签名(长度不定)</li></ul>
* @throws IOException
*/
public byte[] getUserKey(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
int len = in.read();
byte[] emailBin = new byte[len];
if (emailBin.length != in.read(emailBin)) {
ret[0] = ERR_EOF;
return ret;
}
String email = new String(emailBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] passwordBin = new byte[len];
if (passwordBin.length != in.read(passwordBin)) {
in.close();
ret[0] = ERR_EOF;
return ret;
}
String password = new String(passwordBin);
len = in.read();
byte[] idBin = new byte[len];
if (idBin.length != in.read(idBin)) {
ret[0] = ERR_EOF;
return ret;
}
String id = new String(idBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] idPwdBin = new byte[len];
if (idPwdBin.length != in.read(idPwdBin)) {
in.close();
ret[0] = ERR_EOF;
return ret;
}
String idPassword = new String(idPwdBin);
in.close();
User user = userDAO.login(email, password);
if (user == null) {
ret[0] = ERR_WRONG_PWD;
return ret;
}
if (user.getStatus() != User.USER_ACTIVE) {
ret[0] = ERR_NOT_ACTIVE;
return ret;
}
int belongsTo = idRequestDAO.doesIdBelongToUser(id, user, idPassword);
switch (belongsTo) {
case 1:
ret[0] = ERR_WRONG_ID_PWD;
return ret;
case 2:
logger.warn("user with id:" + user.getEmail() + " attemptd to steal id:" + id + " at " + new Date());
ret[0] = ERR_ID_THEFT;
return ret;
}
IdentityDescriptionEntity ide = identityDescriptionBean.get(id);
IdentityDescription userId = ide.getIdentityDescription(idPassword.getBytes());
//System.out.println("start:" + userId.getCertificate().getNoEarlyThan());
//System.out.println("end:" + userId.getCertificate().getNoLateThan());
byte[] idbs = userId.toByteArray();
// TODO debug
//System.out.println("ID content:");
//System.out.println(Hex.hex(idbs));
byte[] succ = new byte[1 + idbs.length];
succ[0] = ERR_SUCCESS;
System.arraycopy(idbs, 0, succ, 1, idbs.length);
Arrays.fill(idbs, (byte) 0);
return succ;
}
/**
* 用户为一个ID申请描述信息
* @param request 请求体 具体内容:<ul><li>
* 用户注册时电子邮件地址(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 用户密码(长度信息1字节 数据最多255字节)</li><li>
* 用户所要使用的IBE系统(4字节)</li><li>
* 要请求的ID(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 用户为要请求的ID所设置的访问密码(长度信息1字节 数据最多255字节)</li></ul>
* @return 包含处理结果的字节数组 长度为1
* @throws IOException
*/
public byte[] applyUserKey(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
int len = in.read();
byte[] emailBin = new byte[len];
if (emailBin.length != in.read(emailBin)) {
ret[0] = ERR_EOF;
return ret;
}
String email = new String(emailBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] passwordBin = new byte[len];
if (passwordBin.length != in.read(passwordBin)) {
in.close();
ret[0] = ERR_EOF;
return ret;
}
String password = new String(passwordBin);
byte[] sysIdBin = new byte[4];
if (4 != in.read(sysIdBin)) {
ret[0] = ERR_EOF;
return ret;
}
int ibeSystemId = Hex.bytesToInt(sysIdBin);
len = in.read();
byte[] idBin = new byte[len];
if (idBin.length != in.read(idBin)) {
ret[0] = ERR_EOF;
return ret;
}
String id = new String(idBin, IBEConstraints.USER_STRING_ENCODING);
int idExist = idRequestDAO.doesIdRequestExist(id);
if (0 < idExist) {
ret[0] = ERR_ID_USED;
return ret;
}
len = in.read();
byte[] idPwdBin = new byte[len];
if (idPwdBin.length != in.read(idPwdBin)) {
in.close();
ret[0] = ERR_EOF;
return ret;
}
String idPassword = new String(idPwdBin);
in.close();
User user = userDAO.login(email, password);
if (user == null) {
ret[0] = ERR_WRONG_PWD;
return ret;
}
if (user.getStatus() != User.USER_ACTIVE) {
ret[0] = ERR_NOT_ACTIVE;
return ret;
}
IDRequest idr = new IDRequest();
idr.setApplicant(user);
idr.setApplicationDate(new Date());
idr.setIbeSystemId(ibeSystemId);
idr.setIdentityString(id);
idr.setPassword(idPassword);
idr.setStatus(IBECSR.APPLICATION_NOT_VERIFIED);
idRequestDAO.add(idr);
ret[0] = ERR_SUCCESS;
return ret;
}
/**
* 注册一个新用户
* @param request 注册用户请求 包含:<ul><li>
* 用户名(长度1字节 内容最多255字节 UTF-8编码)</li><li>
* 电子邮件(长度1字节 内容最多255字节 UTF-8编码)</li><li>
* 密码(长度1字节 内容最多255字节)</li></ul>
* @return 包含处理结果的字节数组 长度为1
* @throws IOException
*/
public byte[] register(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
int len = in.read();
byte[] usernameBin = new byte[len];
if (usernameBin.length != in.read(usernameBin)) {
ret[0] = ERR_EOF;
return ret;
}
String username = new String(usernameBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] emailBin = new byte[len];
if (emailBin.length != in.read(emailBin)) {
ret[0] = ERR_EOF;
return ret;
}
String email = new String(emailBin, IBEConstraints.USER_STRING_ENCODING);
boolean emailExist = userDAO.isEmailExist(email);
if (emailExist) {
ret[0] = ERR_EMAIL_USED;
return ret;
}
len = in.read();
byte[] passwordBin = new byte[len];
if (passwordBin.length != in.read(passwordBin)) {
in.close();
ret[0] = ERR_EOF;
return ret;
}
String password = new String(passwordBin);
in.close();
Date regDate = new Date();
User user = new User();
user.setEmail(email);
user.setUsername(username);
user.setRegDate(regDate);
user.setStatus(User.USER_REG);
String salt = EJBClient.util.format(regDate);
byte[] hash = Hash.sha1(new StringBuilder(password).append(salt).toString());
user.setPassword(Hex.hex(hash));
userDAO.add(user);
ret[0] = ERR_SUCCESS;
return ret;
}
/**
* 列出用户所拥有的ID信息
* @param request 请求体 包含:<ul><li>
* 用户注册时电子邮件地址(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 用户密码(长度信息1字节 数据最多255字节)</li><li>
* 页码 从0开始 长度4字节</li><li>
* 每一页数量 1字节 值从1到255</li><li>
* 当前状态 1字节 默认全部状态</li></ul>
* @return 包含身份请求信息的列表:<ul><li>
* 操作结果 1字节</li><li>
* 身份请求信息数量 1字节</li><li>
* 数个身份请求信息</li></ul>
* @throws IOException
*/
public byte[] listIds(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
int len = in.read();
byte[] emailBin = new byte[len];
if (emailBin.length != in.read(emailBin)) {
ret[0] = ERR_EOF;
return ret;
}
String email = new String(emailBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] passwordBin = new byte[len];
if (passwordBin.length != in.read(passwordBin)){
in.close();
ret[0] = ERR_EOF;
return ret;
}
String password = new String(passwordBin);
byte[] pageBin = new byte[4];
if (pageBin.length != in.read(pageBin)) {
ret[0] = ERR_EOF;
return ret;
}
int page = Hex.bytesToInt(pageBin);
if (page < 0) {
ret[0] = ERR_DATA_ERROR;
return ret;
}
int amount = in.read();
if (amount == -1) {
ret[0] = ERR_EOF;
return ret;
}
int status = in.read();
if (status == -1)
status = 0;
User user = userDAO.login(email, password);
if (user == null) {
ret[0] = ERR_WRONG_PWD;
return ret;
}
if (user.getStatus() != User.USER_ACTIVE) {
ret[0] = ERR_NOT_ACTIVE;
return ret;
}
List<IDRequest> requests = idRequestDAO.list(user, page, amount, status);
ByteArrayOutputStream out = new SecureByteArrayOutputStream();
out.write(ERR_SUCCESS);
out.write(requests.size()); // 最多255个
for (IDRequest idRequest : requests) {
out.write(idRequest.toBytes());
}
out.flush();
byte[] retRqs = out.toByteArray();
out.close();
return retRqs;
}
/**
* 列出当前可用的IBE系统
* @param request 请求 包含:<ul><li>
* 分业页码 从0开始 4字节</li><li>
* 每一页数量 值从1到255 1字节</li></ul>
* @return 系统列表:<ul><li>
* 操作结果 1字节</li><li>
* 本次返回的系统数量 1字节</li><li>
* 系统列表 数字节(每一个系统列表项包含4字节的系统编号 1字节的系统名长度和数字节的系统名)</li></ul>
* @throws IOException
*/
public byte[] listSystems(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
byte[] pageBin = new byte[4];
if (pageBin.length != in.read(pageBin)) {
ret[0] = ERR_EOF;
return ret;
}
int page = Hex.bytesToInt(pageBin);
if (page < 0) {
ret[0] = ERR_DATA_ERROR;
return ret;
}
int amount = in.read();
if (amount == -1) {
ret[0] = ERR_EOF;
return ret;
}
Map<Integer, String> systems = systemBean.list(page, amount);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(ERR_SUCCESS);
out.write(systems.size());
for (Integer sysId : systems.keySet()) {
String sysName = systems.get(sysId);
byte[] sysNameBin = sysName.getBytes(IBEConstraints.USER_STRING_ENCODING);
out.write(Hex.intToByte(sysId.intValue()));
out.write(sysNameBin.length);
out.write(sysNameBin);
}
out.flush();
return out.toByteArray();
}
/**
* 检查用户的电子邮件地址和密码是否匹配
* @param request 请求体 包含:<ul><li>
* 用户注册时电子邮件地址(长度信息1字节 数据最多255字节 UTF-8编码)</li><li>
* 用户密码(长度信息1字节 数据最多255字节)</li></ul>
* @return 包含处理结果的字节数组 长度为1
* @throws IOException
*/
public byte[] login(byte[] request) throws IOException {
byte[] ret = new byte[1];
ByteArrayInputStream in = new SecureByteArrayInputStream(request);
int len = in.read();
byte[] emailBin = new byte[len];
if (emailBin.length != in.read(emailBin)) {
ret[0] = ERR_EOF;
return ret;
}
String email = new String(emailBin, IBEConstraints.USER_STRING_ENCODING);
len = in.read();
byte[] passwordBin = new byte[len];
if (passwordBin.length != in.read(passwordBin)){
in.close();
ret[0] = ERR_EOF;
return ret;
}
String password = new String(passwordBin);
logger.debug(String.format("User %s login at %s, password: %s", email, new Date().toString(), password));
User user = userDAO.login(email, password);
if (user == null) {
logger.debug("Login failure: wrong password for %s", email);
ret[0] = ERR_WRONG_PWD;
return ret;
}
if (user.getStatus() != User.USER_ACTIVE) {
logger.debug("Login failure: user %s not active", user.getUsername());
ret[0] = ERR_NOT_ACTIVE;
return ret;
}
logger.debug("User %s successfully logged in", email);
ret[0] = ERR_SUCCESS;
return ret;
}
public void setIdentityDescriptionBean(IdentityDescriptionBean identityDescriptionBean) {
this.identityDescriptionBean = identityDescriptionBean;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void setIdRequestDAO(IDRequestDAO idRequestDAO) {
this.idRequestDAO = idRequestDAO;
}
public void setSystemBean(IBESystemBean systemBean) {
this.systemBean = systemBean;
}
}