001package top.cenze.utils.crypt.sm.sm2;
002
003import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
004import org.bouncycastle.crypto.digests.SM3Digest;
005import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
006import org.bouncycastle.crypto.params.ECPublicKeyParameters;
007import org.bouncycastle.math.ec.ECPoint;
008import top.cenze.utils.ConvertUtil;
009
010import java.math.BigInteger;
011
012public class Cipher {
013    private int ct;
014    private ECPoint p2;
015    private SM3Digest sm3keybase;
016    private SM3Digest sm3c3;
017    private byte key[];
018    private byte keyOff;
019
020    public Cipher()
021    {
022        this.ct = 1;
023        this.key = new byte[32];
024        this.keyOff = 0;
025    }
026
027    private void Reset()
028    {
029        this.sm3keybase = new SM3Digest();
030        this.sm3c3 = new SM3Digest();
031
032        byte p[] = ConvertUtil.byteConvert32Bytes(p2.getX().toBigInteger());
033        this.sm3keybase.update(p, 0, p.length);
034        this.sm3c3.update(p, 0, p.length);
035
036        p = ConvertUtil.byteConvert32Bytes(p2.getY().toBigInteger());
037        this.sm3keybase.update(p, 0, p.length);
038        this.ct = 1;
039        NextKey();
040    }
041
042    private void NextKey()
043    {
044        SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
045        sm3keycur.update((byte) (ct >> 24 & 0xff));
046        sm3keycur.update((byte) (ct >> 16 & 0xff));
047        sm3keycur.update((byte) (ct >> 8 & 0xff));
048        sm3keycur.update((byte) (ct & 0xff));
049        sm3keycur.doFinal(key, 0);
050        this.keyOff = 0;
051        this.ct++;
052    }
053
054    public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
055    {
056        AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
057        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
058        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
059        BigInteger k = ecpriv.getD();
060        ECPoint c1 = ecpub.getQ();
061        this.p2 = userKey.multiply(k);
062        Reset();
063        return c1;
064    }
065
066    public void Encrypt(byte data[])
067    {
068        this.sm3c3.update(data, 0, data.length);
069        for (int i = 0; i < data.length; i++)
070        {
071            if (keyOff == key.length)
072            {
073                NextKey();
074            }
075            data[i] ^= key[keyOff++];
076        }
077    }
078
079    public void Init_dec(BigInteger userD, ECPoint c1)
080    {
081        this.p2 = c1.multiply(userD);
082        Reset();
083    }
084
085    public void Decrypt(byte data[])
086    {
087        for (int i = 0; i < data.length; i++)
088        {
089            if (keyOff == key.length)
090            {
091                NextKey();
092            }
093            data[i] ^= key[keyOff++];
094        }
095
096        this.sm3c3.update(data, 0, data.length);
097    }
098
099    public void Dofinal(byte c3[])
100    {
101        byte p[] = ConvertUtil.byteConvert32Bytes(p2.getY().toBigInteger());
102        this.sm3c3.update(p, 0, p.length);
103        this.sm3c3.doFinal(c3, 0);
104        Reset();
105    }
106}