1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package io.github.tonywasher.joceanus.gordianknot.impl.bc.sign;
19
20 import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
21 import io.github.tonywasher.joceanus.gordianknot.api.sign.GordianNewSignParams;
22 import io.github.tonywasher.joceanus.gordianknot.api.sign.spec.GordianSignatureSpec;
23 import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyEllipticKeyPair.BouncyECPrivateKey;
24 import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyEllipticKeyPair.BouncyECPublicKey;
25 import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyKeyPair;
26 import io.github.tonywasher.joceanus.gordianknot.impl.bc.sign.BouncySignature.BouncyDSACoder;
27 import io.github.tonywasher.joceanus.gordianknot.impl.core.base.GordianBaseFactory;
28 import io.github.tonywasher.joceanus.gordianknot.impl.core.spec.sign.GordianCoreSignatureSpec;
29 import org.bouncycastle.crypto.params.ParametersWithRandom;
30 import org.bouncycastle.crypto.signers.ECGOST3410Signer;
31
32 import java.math.BigInteger;
33
34
35
36
37 public class BouncyGOSTSignature
38 extends BouncyDigestSignature {
39
40
41
42 private final ECGOST3410Signer theSigner;
43
44
45
46
47 private final BouncyGOSTCoder theCoder;
48
49
50
51
52
53
54
55
56 BouncyGOSTSignature(final GordianBaseFactory pFactory,
57 final GordianSignatureSpec pSpec) throws GordianException {
58
59 super(pFactory, pSpec);
60
61
62 theSigner = new ECGOST3410Signer();
63 theCoder = new BouncyGOSTCoder(((GordianCoreSignatureSpec) pSpec).getDigestSpec().getDigestLength().getByteLength() << 1);
64 }
65
66 @Override
67 public void initForSigning(final GordianNewSignParams pParams) throws GordianException {
68
69 super.initForSigning(pParams);
70 final BouncyKeyPair myPair = getKeyPair();
71 BouncyKeyPair.checkKeyPair(myPair);
72
73
74 final BouncyECPrivateKey myPrivate = (BouncyECPrivateKey) myPair.getPrivateKey();
75 final ParametersWithRandom myParms = new ParametersWithRandom(myPrivate.getPrivateKey(), getRandom());
76 theSigner.init(true, myParms);
77 }
78
79 @Override
80 public void initForVerify(final GordianNewSignParams pParams) throws GordianException {
81
82 super.initForVerify(pParams);
83 final BouncyKeyPair myPair = getKeyPair();
84 BouncyKeyPair.checkKeyPair(myPair);
85
86
87 final BouncyECPublicKey myPublic = (BouncyECPublicKey) myPair.getPublicKey();
88 theSigner.init(false, myPublic.getPublicKey());
89 }
90
91 @Override
92 public byte[] sign() throws GordianException {
93
94 checkMode(GordianSignatureMode.SIGN);
95
96
97 final BigInteger[] myValues = theSigner.generateSignature(getDigest());
98 return theCoder.dsaEncode(myValues[0], myValues[1]);
99 }
100
101 @Override
102 public boolean verify(final byte[] pSignature) throws GordianException {
103
104 checkMode(GordianSignatureMode.VERIFY);
105
106
107 final BigInteger[] myValues = theCoder.dsaDecode(pSignature);
108 return theSigner.verifySignature(getDigest(), myValues[0], myValues[1]);
109 }
110
111
112
113
114 static final class BouncyGOSTCoder
115 implements BouncyDSACoder {
116
117
118
119 private final Integer theLen;
120
121
122
123
124
125
126 BouncyGOSTCoder(final Integer pLen) {
127 theLen = pLen;
128 }
129
130 @Override
131 public byte[] dsaEncode(final BigInteger r,
132 final BigInteger s) {
133
134 final byte[] myFirst = makeUnsigned(s);
135 final byte[] mySecond = makeUnsigned(r);
136 final byte[] myResult = new byte[theLen];
137
138
139 System.arraycopy(myFirst, 0, myResult, theLen / 2 - myFirst.length, myFirst.length);
140 System.arraycopy(mySecond, 0, myResult, theLen - mySecond.length, mySecond.length);
141 return myResult;
142 }
143
144
145
146
147
148
149
150 private static byte[] makeUnsigned(final BigInteger pValue) {
151
152 final byte[] myResult = pValue.toByteArray();
153 if (myResult[0] != 0) {
154 return myResult;
155 }
156
157
158 final byte[] myTmp = new byte[myResult.length - 1];
159 System.arraycopy(myResult, 1, myTmp, 0, myTmp.length);
160 return myTmp;
161 }
162
163 @Override
164 public BigInteger[] dsaDecode(final byte[] pEncoded) {
165
166 final byte[] myFirst = new byte[pEncoded.length / 2];
167 final byte[] mySecond = new byte[pEncoded.length / 2];
168 System.arraycopy(pEncoded, 0, myFirst, 0, myFirst.length);
169 System.arraycopy(pEncoded, myFirst.length, mySecond, 0, mySecond.length);
170
171
172 final BigInteger[] sig = new BigInteger[2];
173 sig[1] = new BigInteger(1, myFirst);
174 sig[0] = new BigInteger(1, mySecond);
175 return sig;
176 }
177 }
178 }