zoukankan      html  css  js  c++  java
  • java 国密算法sm2、sm3

    国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。

    SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。

    SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。

    SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

    SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

    由于SM1、SM4加解密的分组大小为128bit,故对消息进行加解密时,若消息长度过长,需要进行分组,要消息长度不足,则要进行填充。

    java代码下载:

    https://download.csdn.net/download/weixin_30512027/10901805

    pom需添加

    <!--国密-->
    <dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.56</version>
    </dependency>
    sm2:

    public class SM2 {
    private static BigInteger n = new BigInteger(
    "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "7203DF6B" + "21C6052B" + "53BBF409" + "39D54123", 16);
    private static BigInteger p = new BigInteger(
    "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFF", 16);
    private static BigInteger a = new BigInteger(
    "FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFC", 16);
    private static BigInteger b = new BigInteger(
    "28E9FA9E" + "9D9F5E34" + "4D5A9E4B" + "CF6509A7" + "F39789F5" + "15AB8F92" + "DDBCBD41" + "4D940E93", 16);
    private static BigInteger gx = new BigInteger(
    "32C4AE2C" + "1F198119" + "5F990446" + "6A39C994" + "8FE30BBF" + "F2660BE1" + "715A4589" + "334C74C7", 16);
    private static BigInteger gy = new BigInteger(
    "BC3736A2" + "F4F6779C" + "59BDCEE3" + "6B692153" + "D0A9877C" + "C62A4740" + "02DF32E5" + "2139F0A0", 16);
    private static ECDomainParameters ecc_bc_spec;
    private static int w = (int) Math.ceil(n.bitLength() * 1.0 / 2) - 1;
    private static BigInteger _2w = new BigInteger("2").pow(w);
    private static final int DIGEST_LENGTH = 32;

    private static SecureRandom random = new SecureRandom();
    private static ECCurve.Fp curve;
    private static ECPoint G;
    private boolean debug = false;

    public boolean isDebug() {
    return debug;
    }

    public void setDebug(boolean debug) {
    this.debug = debug;
    }

    /**
    * 以16进制打印字节数组
    *
    * @param b
    */
    public static void printHexString(byte[] b) {
    for (int i = 0; i < b.length; i++) {
    String hex = Integer.toHexString(b[i] & 0xFF);
    if (hex.length() == 1) {
    hex = '0' + hex;
    }
    System.out.print(hex.toUpperCase());
    }
    System.out.println();
    }

    /**
    * 随机数生成器
    *
    * @param max
    * @return
    */
    private static BigInteger random(BigInteger max) {

    BigInteger r = new BigInteger(256, random);
    // int count = 1;

    while (r.compareTo(max) >= 0) {
    r = new BigInteger(128, random);
    // count++;
    }

    // System.out.println("count: " + count);
    return r;
    }

    /**
    * 判断字节数组是否全0
    *
    * @param buffer
    * @return
    */
    private boolean allZero(byte[] buffer) {
    for (int i = 0; i < buffer.length; i++) {
    if (buffer[i] != 0)
    return false;
    }
    return true;
    }

    /**
    * 公钥加密
    *
    * @param input
    * 加密原文
    * @param publicKey
    * 公钥
    * @return
    */
    public byte[] encrypt(String input, ECPoint publicKey) {

    byte[] inputBuffer = input.getBytes();
    if (debug)
    printHexString(inputBuffer);

    byte[] C1Buffer;
    ECPoint kpb;
    byte[] t;
    do {
    /* 1 产生随机数k,k属于[1, n-1] */
    BigInteger k = random(n);
    if (debug) {
    System.out.print("k: ");
    printHexString(k.toByteArray());
    }

    /* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */
    ECPoint C1 = G.multiply(k);
    C1Buffer = C1.getEncoded(false);
    if (debug) {
    System.out.print("C1: ");
    printHexString(C1Buffer);
    }

    /*
    * 3 计算椭圆曲线点 S = [h]Pb
    */
    BigInteger h = ecc_bc_spec.getH();
    if (h != null) {
    ECPoint S = publicKey.multiply(h);
    if (S.isInfinity())
    throw new IllegalStateException();
    }

    /* 4 计算 [k]PB = (x2, y2) */
    kpb = publicKey.multiply(k).normalize();

    /* 5 计算 t = KDF(x2||y2, klen) */
    byte[] kpbBytes = kpb.getEncoded(false);
    t = KDF(kpbBytes, inputBuffer.length);
    // DerivationFunction kdf = new KDF1BytesGenerator(new
    // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
    //
    // t = new byte[inputBuffer.length];
    // kdf.init(new ISO18033KDFParameters(kpbBytes));
    // kdf.generateBytes(t, 0, t.length);
    } while (allZero(t));

    /* 6 计算C2=M^t */
    byte[] C2 = new byte[inputBuffer.length];
    for (int i = 0; i < inputBuffer.length; i++) {
    C2[i] = (byte) (inputBuffer[i] ^ t[i]);
    }

    /* 7 计算C3 = Hash(x2 || M || y2) */
    byte[] C3 = sm3hash(kpb.getXCoord().toBigInteger().toByteArray(), inputBuffer,
    kpb.getYCoord().toBigInteger().toByteArray());

    /* 8 输出密文 C=C1 || C2 || C3 */

    byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];

    System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);
    System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);
    System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length, C3.length);

    if (debug) {
    System.out.print("密文: ");
    printHexString(encryptResult);
    }

    return encryptResult;
    }

    /**
    * 私钥解密
    *
    * @param encryptData
    * 密文数据字节数组
    * @param privateKey
    * 解密私钥
    * @return
    */
    public String decrypt(byte[] encryptData, BigInteger privateKey) {

    if (debug)
    System.out.println("encryptData length: " + encryptData.length);

    byte[] C1Byte = new byte[65];
    System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);

    ECPoint C1 = curve.decodePoint(C1Byte).normalize();

    /*
    * 计算椭圆曲线点 S = [h]C1 是否为无穷点
    */
    BigInteger h = ecc_bc_spec.getH();
    if (h != null) {
    ECPoint S = C1.multiply(h);
    if (S.isInfinity())
    throw new IllegalStateException();
    }
    /* 计算[dB]C1 = (x2, y2) */
    ECPoint dBC1 = C1.multiply(privateKey).normalize();

    /* 计算t = KDF(x2 || y2, klen) */
    byte[] dBC1Bytes = dBC1.getEncoded(false);
    int klen = encryptData.length - 65 - DIGEST_LENGTH;
    byte[] t = KDF(dBC1Bytes, klen);
    // DerivationFunction kdf = new KDF1BytesGenerator(new
    // ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));
    // if (debug)
    // System.out.println("klen = " + klen);
    // kdf.init(new ISO18033KDFParameters(dBC1Bytes));
    // kdf.generateBytes(t, 0, t.length);

    if (allZero(t)) {
    System.err.println("all zero");
    throw new IllegalStateException();
    }

    /* 5 计算M'=C2^t */
    byte[] M = new byte[klen];
    for (int i = 0; i < M.length; i++) {
    M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);
    }
    if (debug)
    printHexString(M);

    /* 6 计算 u = Hash(x2 || M' || y2) 判断 u == C3是否成立 */
    byte[] C3 = new byte[DIGEST_LENGTH];

    if (debug)
    try {
    System.out.println("M = " + new String(M, "UTF8"));
    } catch (UnsupportedEncodingException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }

    System.arraycopy(encryptData, encryptData.length - DIGEST_LENGTH, C3, 0, DIGEST_LENGTH);
    byte[] u = sm3hash(dBC1.getXCoord().toBigInteger().toByteArray(), M,
    dBC1.getYCoord().toBigInteger().toByteArray());
    if (Arrays.equals(u, C3)) {
    if (debug)
    System.out.println("解密成功");
    try {
    return new String(M, "UTF8");
    } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    }
    return null;
    } else {
    if (debug) {
    System.out.print("u = ");
    printHexString(u);
    System.out.print("C3 = ");
    printHexString(C3);
    System.err.println("解密验证失败");
    }
    return null;
    }

    }

    // /**
    // * SHA摘要
    // * @param x2
    // * @param M
    // * @param y2
    // * @return
    // */
    // private byte[] calculateHash(BigInteger x2, byte[] M, BigInteger y2) {
    // ShortenedDigest digest = new ShortenedDigest(new SHA256Digest(),
    // DIGEST_LENGTH);
    // byte[] buf = x2.toByteArray();
    // digest.update(buf, 0, buf.length);
    // digest.update(M, 0, M.length);
    // buf = y2.toByteArray();
    // digest.update(buf, 0, buf.length);
    //
    // buf = new byte[DIGEST_LENGTH];
    // digest.doFinal(buf, 0);
    //
    // return buf;
    // }

    /**
    * 判断是否在范围内
    *
    * @param param
    * @param min
    * @param max
    * @return
    */
    private boolean between(BigInteger param, BigInteger min, BigInteger max) {
    if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) {
    return true;
    } else {
    return false;
    }
    }

    /**
    * 判断生成的公钥是否合法
    *
    * @param publicKey
    * @return
    */
    private boolean checkPublicKey(ECPoint publicKey) {

    if (!publicKey.isInfinity()) {

    BigInteger x = publicKey.getXCoord().toBigInteger();
    BigInteger y = publicKey.getYCoord().toBigInteger();

    if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {

    BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);

    if (debug)
    System.out.println("xResult: " + xResult.toString());

    BigInteger yResult = y.pow(2).mod(p);

    if (debug)
    System.out.println("yResult: " + yResult.toString());

    if (yResult.equals(xResult) && publicKey.multiply(n).isInfinity()) {
    return true;
    }
    }
    }
    return false;
    }

    /**
    * 生成密钥对
    *
    * @return
    */
    public SM2KeyPair generateKeyPair() {

    BigInteger d = random(n.subtract(new BigInteger("1")));

    SM2KeyPair keyPair = new SM2KeyPair(G.multiply(d).normalize(), d);

    if (checkPublicKey(keyPair.getPublicKey())) {
    if (debug)
    System.out.println("generate key successfully");
    return keyPair;
    } else {
    if (debug)
    System.err.println("generate key failed");
    return null;
    }
    }

    public SM2() {
    curve = new ECCurve.Fp(p, // q
    a, // a
    b); // b
    G = curve.createPoint(gx, gy);
    ecc_bc_spec = new ECDomainParameters(curve, G, n);
    }

    public SM2(boolean debug) {
    this();
    this.debug = debug;
    }

    /**
    * 导出公钥到本地
    *
    * @param publicKey
    * @param path
    */
    public void exportPublicKey(ECPoint publicKey, String path) {
    File file = new File(path);
    try {
    if (!file.exists())
    file.createNewFile();
    byte buffer[] = publicKey.getEncoded(false);
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(buffer);
    fos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * 从本地导入公钥
    *
    * @param path
    * @return
    */
    public ECPoint importPublicKey(String path) {
    File file = new File(path);
    try {
    if (!file.exists())
    return null;
    FileInputStream fis = new FileInputStream(file);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    byte buffer[] = new byte[16];
    int size;
    while ((size = fis.read(buffer)) != -1) {
    baos.write(buffer, 0, size);
    }
    fis.close();
    return curve.decodePoint(baos.toByteArray());
    } catch (IOException e) {
    e.printStackTrace();
    }
    return null;
    }

    /**
    * 导出私钥到本地
    *
    * @param privateKey
    * @param path
    */
    public void exportPrivateKey(BigInteger privateKey, String path) {
    File file = new File(path);
    try {
    if (!file.exists())
    file.createNewFile();
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
    oos.writeObject(privateKey);
    oos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * 从本地导入私钥
    *
    * @param path
    * @return
    */
    public BigInteger importPrivateKey(String path) {
    File file = new File(path);
    try {
    if (!file.exists())
    return null;
    FileInputStream fis = new FileInputStream(file);
    ObjectInputStream ois = new ObjectInputStream(fis);
    BigInteger res = (BigInteger) (ois.readObject());
    ois.close();
    fis.close();
    return res;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**
    * 字节数组拼接
    *
    * @param params
    * @return
    */
    private static byte[] join(byte[]... params) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] res = null;
    try {
    for (int i = 0; i < params.length; i++) {
    baos.write(params[i]);
    }
    res = baos.toByteArray();
    } catch (IOException e) {
    e.printStackTrace();
    }
    return res;
    }

    /**
    * sm3摘要
    *
    * @param params
    * @return
    */
    private static byte[] sm3hash(byte[]... params) {
    byte[] res = null;
    try {
    res = SM3.hash(join(params));
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    return res;
    }

    /**
    * 取得用户标识字节数组
    *
    * @param IDA
    * @param aPublicKey
    * @return
    */
    private static byte[] ZA(String IDA, ECPoint aPublicKey) {
    byte[] idaBytes = IDA.getBytes();
    int entlenA = idaBytes.length * 8;
    byte[] ENTLA = new byte[] { (byte) (entlenA & 0xFF00), (byte) (entlenA & 0x00FF) };
    byte[] ZA = sm3hash(ENTLA, idaBytes, a.toByteArray(), b.toByteArray(), gx.toByteArray(), gy.toByteArray(),
    aPublicKey.getXCoord().toBigInteger().toByteArray(),
    aPublicKey.getYCoord().toBigInteger().toByteArray());
    return ZA;
    }

    /**
    * 签名
    *
    * @param M
    * 签名信息
    * @param IDA
    * 签名方唯一标识
    * @param keyPair
    * 签名方密钥对
    * @return 签名
    */
    public Signature sign(String M, String IDA, SM2KeyPair keyPair) {
    byte[] ZA = ZA(IDA, keyPair.getPublicKey());
    byte[] M_ = join(ZA, M.getBytes());
    BigInteger e = new BigInteger(1, sm3hash(M_));
    // BigInteger k = new BigInteger(
    // "6CB28D99 385C175C 94F94E93 4817663F C176D925 DD72B727 260DBAAE
    // 1FB2F96F".replace(" ", ""), 16);
    BigInteger k;
    BigInteger r;
    do {
    k = random(n);
    ECPoint p1 = G.multiply(k).normalize();
    BigInteger x1 = p1.getXCoord().toBigInteger();
    r = e.add(x1);
    r = r.mod(n);
    } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));

    BigInteger s = ((keyPair.getPrivateKey().add(BigInteger.ONE).modInverse(n))
    .multiply((k.subtract(r.multiply(keyPair.getPrivateKey()))).mod(n))).mod(n);

    return new Signature(r, s);
    }

    /**
    * 验签
    *
    * @param M
    * 签名信息
    * @param signature
    * 签名
    * @param IDA
    * 签名方唯一标识
    * @param aPublicKey
    * 签名方公钥
    * @return true or false
    */
    public boolean verify(String M, Signature signature, String IDA, ECPoint aPublicKey) {
    if (!between(signature.r, BigInteger.ONE, n))
    return false;
    if (!between(signature.s, BigInteger.ONE, n))
    return false;

    byte[] M_ = join(ZA(IDA, aPublicKey), M.getBytes());
    BigInteger e = new BigInteger(1, sm3hash(M_));
    BigInteger t = signature.r.add(signature.s).mod(n);

    if (t.equals(BigInteger.ZERO))
    return false;

    ECPoint p1 = G.multiply(signature.s).normalize();
    ECPoint p2 = aPublicKey.multiply(t).normalize();
    BigInteger x1 = p1.add(p2).normalize().getXCoord().toBigInteger();
    BigInteger R = e.add(x1).mod(n);
    if (R.equals(signature.r))
    return true;
    return false;
    }

    /**
    * 密钥派生函数
    *
    * @param Z
    * @param klen
    * 生成klen字节数长度的密钥
    * @return
    */
    private static byte[] KDF(byte[] Z, int klen) {
    int ct = 1;
    int end = (int) Math.ceil(klen * 1.0 / 32);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
    for (int i = 1; i < end; i++) {
    baos.write(sm3hash(Z, SM3.toByteArray(ct)));
    ct++;
    }
    byte[] last = sm3hash(Z, SM3.toByteArray(ct));
    if (klen % 32 == 0) {
    baos.write(last);
    } else
    baos.write(last, 0, klen % 32);
    return baos.toByteArray();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**
    * 传输实体类
    *
    * @author Potato
    *
    */
    private static class TransportEntity implements Serializable {
    final byte[] R; //R点
    final byte[] S; //验证S
    final byte[] Z; //用户标识
    final byte[] K; //公钥

    public TransportEntity(byte[] r, byte[] s,byte[] z,ECPoint pKey) {
    R = r;
    S = s;
    Z=z;
    K=pKey.getEncoded(false);
    }
    }

    /**
    * 密钥协商辅助类
    *
    * @author Potato
    *
    */
    public static class KeyExchange {
    BigInteger rA;
    ECPoint RA;
    ECPoint V;
    byte[] Z;
    byte[] key;

    String ID;
    SM2KeyPair keyPair;

    public KeyExchange(String ID,SM2KeyPair keyPair) {
    this.ID=ID;
    this.keyPair = keyPair;
    this.Z=ZA(ID, keyPair.getPublicKey());
    }

    /**
    * 密钥协商发起第一步
    *
    * @return
    */
    public TransportEntity keyExchange_1() {
    rA = random(n);
    // rA=new BigInteger("83A2C9C8 B96E5AF7 0BD480B4 72409A9A 327257F1
    // EBB73F5B 073354B2 48668563".replace(" ", ""),16);
    RA = G.multiply(rA).normalize();
    return new TransportEntity(RA.getEncoded(false), null,Z,keyPair.getPublicKey());
    }

    /**
    * 密钥协商响应方
    *
    * @param entity 传输实体
    * @return
    */
    public TransportEntity keyExchange_2(TransportEntity entity) {
    BigInteger rB = random(n);
    // BigInteger rB=new BigInteger("33FE2194 0342161C 55619C4A 0C060293
    // D543C80A F19748CE 176D8347 7DE71C80".replace(" ", ""),16);
    ECPoint RB = G.multiply(rB).normalize();

    this.rA=rB;
    this.RA=RB;

    BigInteger x2 = RB.getXCoord().toBigInteger();
    x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));

    BigInteger tB = keyPair.getPrivateKey().add(x2.multiply(rB)).mod(n);
    ECPoint RA = curve.decodePoint(entity.R).normalize();

    BigInteger x1 = RA.getXCoord().toBigInteger();
    x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));

    ECPoint aPublicKey=curve.decodePoint(entity.K).normalize();
    ECPoint temp = aPublicKey.add(RA.multiply(x1).normalize()).normalize();
    ECPoint V = temp.multiply(ecc_bc_spec.getH().multiply(tB)).normalize();
    if (V.isInfinity())
    throw new IllegalStateException();
    this.V=V;

    byte[] xV = V.getXCoord().toBigInteger().toByteArray();
    byte[] yV = V.getYCoord().toBigInteger().toByteArray();
    byte[] KB = KDF(join(xV, yV, entity.Z, this.Z), 16);
    key = KB;
    System.out.print("协商得B密钥:");
    printHexString(KB);
    byte[] sB = sm3hash(new byte[] { 0x02 }, yV,
    sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),
    RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
    RB.getYCoord().toBigInteger().toByteArray()));
    return new TransportEntity(RB.getEncoded(false), sB,this.Z,keyPair.getPublicKey());
    }

    /**
    * 密钥协商发起方第二步
    *
    * @param entity 传输实体
    */
    public TransportEntity keyExchange_3(TransportEntity entity) {
    BigInteger x1 = RA.getXCoord().toBigInteger();
    x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));

    BigInteger tA = keyPair.getPrivateKey().add(x1.multiply(rA)).mod(n);
    ECPoint RB = curve.decodePoint(entity.R).normalize();

    BigInteger x2 = RB.getXCoord().toBigInteger();
    x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));

    ECPoint bPublicKey=curve.decodePoint(entity.K).normalize();
    ECPoint temp = bPublicKey.add(RB.multiply(x2).normalize()).normalize();
    ECPoint U = temp.multiply(ecc_bc_spec.getH().multiply(tA)).normalize();
    if (U.isInfinity())
    throw new IllegalStateException();
    this.V=U;

    byte[] xU = U.getXCoord().toBigInteger().toByteArray();
    byte[] yU = U.getYCoord().toBigInteger().toByteArray();
    byte[] KA = KDF(join(xU, yU,
    this.Z, entity.Z), 16);
    key = KA;
    System.out.print("协商得A密钥:");
    printHexString(KA);
    byte[] s1= sm3hash(new byte[] { 0x02 }, yU,
    sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),
    RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
    RB.getYCoord().toBigInteger().toByteArray()));
    if(Arrays.equals(entity.S, s1))
    System.out.println("B->A 密钥确认成功");
    else
    System.out.println("B->A 密钥确认失败");
    byte[] sA= sm3hash(new byte[] { 0x03 }, yU,
    sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),
    RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),
    RB.getYCoord().toBigInteger().toByteArray()));

    return new TransportEntity(RA.getEncoded(false), sA,this.Z,keyPair.getPublicKey());
    }

    /**
    * 密钥确认最后一步
    *
    * @param entity 传输实体
    */
    public void keyExchange_4(TransportEntity entity) {
    byte[] xV = V.getXCoord().toBigInteger().toByteArray();
    byte[] yV = V.getYCoord().toBigInteger().toByteArray();
    ECPoint RA = curve.decodePoint(entity.R).normalize();
    byte[] s2= sm3hash(new byte[] { 0x03 }, yV,
    sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),
    RA.getYCoord().toBigInteger().toByteArray(), this.RA.getXCoord().toBigInteger().toByteArray(),
    this.RA.getYCoord().toBigInteger().toByteArray()));
    if(Arrays.equals(entity.S, s2))
    System.out.println("A->B 密钥确认成功");
    else
    System.out.println("A->B 密钥确认失败");
    }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {

    SM2 sm02 = new SM2();

    System.out.println("-----------------公钥加密与解密-----------------");
    ECPoint publicKey = sm02.importPublicKey("E:/publickey.pem");
    BigInteger privateKey = sm02.importPrivateKey("E:/privatekey.pem");
    byte[] data = sm02.encrypt("测试加密aaaaaaaaaaa123aabb", publicKey);
    System.out.print("密文:");
    SM2.printHexString(data);
    System.out.println("解密后明文:" + sm02.decrypt(data, privateKey));

    System.out.println("-----------------签名与验签-----------------");
    String IDA = "Heartbeats";
    String M = "要签名的信息";
    Signature signature = sm02.sign(M, IDA, new SM2KeyPair(publicKey, privateKey));
    System.out.println("用户标识:" + IDA);
    System.out.println("签名信息:" + M);
    System.out.println("数字签名:" + signature);
    System.out.println("验证签名:" + sm02.verify(M, signature, IDA, publicKey));

    System.out.println("-----------------密钥协商-----------------");
    String aID = "AAAAAAAAAAAAA";
    SM2KeyPair aKeyPair = sm02.generateKeyPair();
    KeyExchange aKeyExchange = new KeyExchange(aID,aKeyPair);

    String bID = "BBBBBBBBBBBBB";
    SM2KeyPair bKeyPair = sm02.generateKeyPair();
    KeyExchange bKeyExchange = new KeyExchange(bID,bKeyPair);
    TransportEntity entity1 = aKeyExchange.keyExchange_1();
    TransportEntity entity2 = bKeyExchange.keyExchange_2(entity1);
    TransportEntity entity3 = aKeyExchange.keyExchange_3(entity2);
    bKeyExchange.keyExchange_4(entity3);
    }

    public static class Signature {
    BigInteger r;
    BigInteger s;

    public Signature(BigInteger r, BigInteger s) {
    this.r = r;
    this.s = s;
    }

    public String toString() {
    return r.toString(16) + "," + s.toString(16);
    }
    }
    }
    sm3:

    public class SM3 {

    private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
    '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    private static final String ivHexStr = "7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e";
    private static final BigInteger IV = new BigInteger(ivHexStr.replaceAll(" ",
    ""), 16);
    private static final Integer Tj15 = Integer.valueOf("79cc4519", 16);
    private static final Integer Tj63 = Integer.valueOf("7a879d8a", 16);
    private static final byte[] FirstPadding = {(byte) 0x80};
    private static final byte[] ZeroPadding = {(byte) 0x00};

    private static int T(int j) {
    if (j >= 0 && j <= 15) {
    return Tj15.intValue();
    } else if (j >= 16 && j <= 63) {
    return Tj63.intValue();
    } else {
    throw new RuntimeException("data invalid");
    }
    }

    private static Integer FF(Integer x, Integer y, Integer z, int j) {
    if (j >= 0 && j <= 15) {
    return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
    } else if (j >= 16 && j <= 63) {
    return Integer.valueOf((x.intValue() & y.intValue())
    | (x.intValue() & z.intValue())
    | (y.intValue() & z.intValue()));
    } else {
    throw new RuntimeException("data invalid");
    }
    }

    private static Integer GG(Integer x, Integer y, Integer z, int j) {
    if (j >= 0 && j <= 15) {
    return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
    } else if (j >= 16 && j <= 63) {
    return Integer.valueOf((x.intValue() & y.intValue())
    | (~x.intValue() & z.intValue()));
    } else {
    throw new RuntimeException("data invalid");
    }
    }

    private static Integer P0(Integer x) {
    return Integer.valueOf(x.intValue()
    ^ Integer.rotateLeft(x.intValue(), 9)
    ^ Integer.rotateLeft(x.intValue(), 17));
    }

    private static Integer P1(Integer x) {
    return Integer.valueOf(x.intValue()
    ^ Integer.rotateLeft(x.intValue(), 15)
    ^ Integer.rotateLeft(x.intValue(), 23));
    }

    private static byte[] padding(byte[] source) throws IOException {
    if (source.length >= 0x2000000000000000l) {
    throw new RuntimeException("src data invalid.");
    }
    long l = source.length * 8;
    long k = 448 - (l + 1) % 512;
    if (k < 0) {
    k = k + 512;
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(source);
    baos.write(FirstPadding);
    long i = k - 7;
    while (i > 0) {
    baos.write(ZeroPadding);
    i -= 8;
    }
    baos.write(long2bytes(l));
    return baos.toByteArray();
    }

    private static byte[] long2bytes(long l) {
    byte[] bytes = new byte[8];
    for (int i = 0; i < 8; i++) {
    bytes[i] = (byte) (l >>> ((7 - i) * 8));
    }
    return bytes;
    }

    public static byte[] hash(byte[] source) throws IOException {
    byte[] m1 = padding(source);
    int n = m1.length / (512 / 8);
    byte[] b;
    byte[] vi = IV.toByteArray();
    byte[] vi1 = null;
    for (int i = 0; i < n; i++) {
    b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
    vi1 = CF(vi, b);
    vi = vi1;
    }
    return vi1;
    }

    private static byte[] CF(byte[] vi, byte[] bi) throws IOException {
    int a, b, c, d, e, f, g, h;
    a = toInteger(vi, 0);
    b = toInteger(vi, 1);
    c = toInteger(vi, 2);
    d = toInteger(vi, 3);
    e = toInteger(vi, 4);
    f = toInteger(vi, 5);
    g = toInteger(vi, 6);
    h = toInteger(vi, 7);

    int[] w = new int[68];
    int[] w1 = new int[64];
    for (int i = 0; i < 16; i++) {
    w[i] = toInteger(bi, i);
    }
    for (int j = 16; j < 68; j++) {
    w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15))
    ^ Integer.rotateLeft(w[j - 13], 7) ^ w[j - 6];
    }
    for (int j = 0; j < 64; j++) {
    w1[j] = w[j] ^ w[j + 4];
    }
    int ss1, ss2, tt1, tt2;
    for (int j = 0; j < 64; j++) {
    ss1 = Integer
    .rotateLeft(
    Integer.rotateLeft(a, 12) + e
    + Integer.rotateLeft(T(j), j), 7);
    ss2 = ss1 ^ Integer.rotateLeft(a, 12);
    tt1 = FF(a, b, c, j) + d + ss2 + w1[j];
    tt2 = GG(e, f, g, j) + h + ss1 + w[j];
    d = c;
    c = Integer.rotateLeft(b, 9);
    b = a;
    a = tt1;
    h = g;
    g = Integer.rotateLeft(f, 19);
    f = e;
    e = P0(tt2);
    }
    byte[] v = toByteArray(a, b, c, d, e, f, g, h);
    for (int i = 0; i < v.length; i++) {
    v[i] = (byte) (v[i] ^ vi[i]);
    }
    return v;
    }

    private static int toInteger(byte[] source, int index) {
    StringBuilder valueStr = new StringBuilder("");
    for (int i = 0; i < 4; i++) {
    valueStr.append(hexDigits[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);
    valueStr.append(hexDigits[(byte) (source[index * 4 + i] & 0x0F)]);
    }
    return Long.valueOf(valueStr.toString(), 16).intValue();

    }

    private static byte[] toByteArray(int a, int b, int c, int d, int e, int f,
    int g, int h) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
    baos.write(toByteArray(a));
    baos.write(toByteArray(b));
    baos.write(toByteArray(c));
    baos.write(toByteArray(d));
    baos.write(toByteArray(e));
    baos.write(toByteArray(f));
    baos.write(toByteArray(g));
    baos.write(toByteArray(h));
    return baos.toByteArray();
    }

    public static byte[] toByteArray(int i) {
    byte[] byteArray = new byte[4];
    byteArray[0] = (byte) (i >>> 24);
    byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);
    byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);
    byteArray[3] = (byte) (i & 0xFF);
    return byteArray;
    }
    private static String byteToHexString(byte b) {
    int n = b;
    if (n < 0)
    n = 256 + n;
    int d1 = n / 16;
    int d2 = n % 16;
    return ""+hexDigits[d1] + hexDigits[d2];
    }

    public static String byteArrayToHexString(byte[] b) {
    StringBuffer resultSb = new StringBuffer();
    for (int i = 0; i < b.length; i++) {
    resultSb.append(byteToHexString(b[i]));
    }
    return resultSb.toString();
    }

    public static void main(String[] args) throws IOException {
    System.out.println(SM3.byteArrayToHexString(SM3.hash("test".getBytes())));
    }
    }
    ————————————————
    版权声明:本文为CSDN博主「程序猿吉良吉影」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_30512027/article/details/86013878

  • 相关阅读:
    getter 和 setter方法
    了解coredata 数据库的博客
    iOS 本地缓存简述
    iOS 9.0 xcode7
    iOS 直播推流SDK -- PLCameraStreamingKit
    时间充裕的时候看看技术总结
    技术分享7
    学习笔记-音频编解码
    学习笔记-weak strong ARC mrc
    飘雪效果的swf
  • 原文地址:https://www.cnblogs.com/javalinux/p/14550676.html
Copyright © 2011-2022 走看看