package minsecurity.identity; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import minsecurity.Common; import minsecurity.certificate.cert.CertException; import minsecurity.certificate.cert.Certificate; import minsecurity.crypto.KeyUtils; import minsecurity.crypto.PrivateKeyInterface; import minsecurity.crypto.PublicKeyInterface; import minsecurity.crypto.SM4; import minsecurity.crypto.sm2.SM2PrivateKey; import minsecurity.crypto.sm2.SM2PublicKey; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.slf4j.LoggerFactory; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.io.Serializable; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.Arrays; import java.util.Base64; /* * @Author: hongyu guo * @Description: * @Version: 1.0.0 * @Date: 20:25 2021/03/07 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class Identity { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Identity.class); private String Name; private KeyParam KeyParam; private PrivateKeyInterface Prikey; private byte[] PrikeyRawByte; private PublicKeyInterface Pubkey; private String Passwd; private Certificate Cert; private boolean IsDefault; public Identity(String name, KeyParam keyParam, PrivateKeyInterface prikey, byte[] prikeyRawByte, PublicKeyInterface pubkey, String passwd, Certificate cert, boolean isDefault) { Name = name; KeyParam = keyParam; Prikey = prikey; PrikeyRawByte = prikeyRawByte; Pubkey = pubkey; Passwd = passwd; Cert = cert; IsDefault = isDefault; } public Identity(){} public byte[] sign(byte[] digest) throws CryptoException { if(this.Prikey == null) return null; switch (this.KeyParam.PublicKeyAlgorithm){ case Common.SM2: SM2PrivateKey sm2PrivateKey = (SM2PrivateKey) this.Prikey; switch (this.KeyParam.SignatureAlgorithm){ case Common.SM3withSM2: return sm2PrivateKey.sign(digest); default: return null; } default: return null; } } public boolean verify(byte[] msg, byte[] digest) { if(this.Pubkey == null) return false; switch (this.KeyParam.PublicKeyAlgorithm){ case Common.SM2: SM2PublicKey sm2PublicKey = (SM2PublicKey) this.Pubkey; switch (this.KeyParam.SignatureAlgorithm){ case Common.SM3withSM2: return sm2PublicKey.verify(msg, digest); default: return false; } default: return false; } } public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException { if(this.Prikey == null) return null; return this.Prikey.decrypt(cipher); } public byte[] encrypt(byte[] content) throws InvalidCipherTextException { if(this.Pubkey == null) return null; return this.Pubkey.encrypt(content); } public byte[] dump(String passwd) throws NoSuchPaddingException, InvalidAlgorithmParameterException, CertException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); InnerIdentity innerIdentity = IdentityUtil.parseIdentityToInner(this); byte[] bytesOfInnerIdentity = mapper.writeValueAsBytes(innerIdentity); // logger.debug(ByteUtils.toHexString(bytesOfInnerIdentity)); if(passwd != null && passwd.length() != 0) { byte[] sm4key = KeyUtils.get16bytePasswd(passwd.getBytes()); byte[] cipher = SM4.encrypt_CBC_Padding(sm4key, new byte[16], bytesOfInnerIdentity); return Base64.getEncoder().encode(cipher); } return Base64.getEncoder().encode(bytesOfInnerIdentity); } public static Identity load(byte[] data, String passwd) throws BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException, CertException { byte[] bytesOfIdentity = Base64.getDecoder().decode(data); byte[] plain; if(passwd != null && passwd.length() != 0){ byte[] sm4Key = KeyUtils.get16bytePasswd(passwd.getBytes()); plain = SM4.decrypt_CBC_Padding(sm4Key, new byte[16], bytesOfIdentity); } else{ plain = bytesOfIdentity; } ObjectMapper mapper = new ObjectMapper(); InnerIdentity innerIdentity = null; // logger.debug(ByteUtils.toHexString(plain)); try { innerIdentity = mapper.readValue(plain, InnerIdentity.class); } catch (IOException e) { e.printStackTrace(); } return IdentityUtil.parseInnerToIdentity(innerIdentity); } // TODO: passwd ??? public boolean lock(String passwd, int algo) throws IdentityException { switch (algo){ case Common.SM4ECB: if (passwd.length() != 16){ throw new IdentityException("密码应为16位"); } PrikeyRawByte = Prikey.getBytes(); Prikey = null; return true; default: return false; } } public boolean isLocked(){ return PrikeyRawByte != null && PrikeyRawByte.length > 0; } // TODO: passwd ??? public boolean unLock(String passwd, int algo) throws IdentityException { switch (algo) { case Common.SM4ECB: if(passwd == null || passwd.length() == 0) return false; PrivateKeyInterface privateKey = KeyUtils.unMarshalPrivateKey(PrikeyRawByte, KeyParam.PublicKeyAlgorithm); Prikey = privateKey; PrikeyRawByte = null; return true; default: throw new IdentityException("未知对称加密算法"); } } public boolean hasPrivateKey() { return Prikey != null || (PrikeyRawByte != null && PrikeyRawByte.length > 0); } public String getName() { return Name; } public void setName(String name) { Name = name; } public minsecurity.identity.KeyParam getKeyParam() { return KeyParam; } public void setKeyParam(minsecurity.identity.KeyParam keyParam) { KeyParam = keyParam; } public PrivateKeyInterface getPrikey() { return Prikey; } public void setPrikey(PrivateKeyInterface prikey) { Prikey = prikey; } public byte[] getPrikeyRawByte() { return PrikeyRawByte; } public void setPrikeyRawByte(byte[] prikeyRawByte) { PrikeyRawByte = prikeyRawByte; } public PublicKeyInterface getPubkey() { return Pubkey; } public void setPubkey(PublicKeyInterface pubkey) { Pubkey = pubkey; } public String getPasswd() { return Passwd; } public void setPasswd(String passwd) { Passwd = passwd; } public Certificate getCert() { return Cert; } public void setCert(Certificate cert) { Cert = cert; } public boolean isDefault() { return IsDefault; } public void setDefault(boolean aDefault) { IsDefault = aDefault; } @Override public String toString() { return "Identity{" + "Name='" + Name + '\'' + ", KeyParam.signAlgo=" + KeyParam.SignatureAlgorithm + ", KeyParam.pubAlgo=" + KeyParam.PublicKeyAlgorithm + ", Prikey=" + ByteUtils.toHexString(Prikey.getBytes()) + ", pubKey=" + ByteUtils.toHexString(Pubkey.getBytes()) + ", PrikeyRawByte=" + (PrikeyRawByte == null ? "null":ByteUtils.toHexString(PrikeyRawByte)) + ", Pubkey=" + Pubkey + ", Passwd='" + Passwd + '\'' + ", Cert=" + Cert + ", isDefault=" + IsDefault + '}'; } }