Skip to content

Instantly share code, notes, and snippets.

@muromec

muromec/K.cs Secret

Last active January 5, 2018 11:55
Show Gist options
  • Save muromec/cfe8da5135084bea50aff5670bde110f to your computer and use it in GitHub Desktop.
Save muromec/cfe8da5135084bea50aff5670bde110f to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Collectionsusing System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Linq;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.UA;
using Org.BouncyCastle.Asn1.Ess;
using Org.BouncyCastle.Utilities.Test;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.X509;
public class K {
static readonly byte[] sBoxParam = {
0xA,0x9,0xD,0x6,0xE,0xB,0x4,0x5,0xF,0x1,0x3,0xC,0x7,0x0,0x8,0x2, // K1
0x8,0x0,0xC,0x4,0x9,0x6,0x7,0xB,0x2,0x3,0x1,0xF,0x5,0xE,0xA,0xD, // K2
0xF,0x6,0x5,0x8,0xE,0xB,0xA,0x4,0xC,0x0,0x3,0x7,0x2,0x9,0x1,0xD, // K3
0x3,0x8,0xD,0x9,0x6,0xB,0xF,0x0,0x2,0x5,0xC,0xA,0x4,0xE,0x1,0x7, // K4
0xF,0x8,0xE,0x9,0x7,0x2,0x0,0xD,0xC,0x6,0x1,0x5,0xB,0x4,0x3,0xA, // K5
0x2,0x8,0x9,0x7,0x5,0xF,0x0,0xB,0xC,0x1,0xD,0xE,0xA,0x3,0x6,0x4, // K6
0x3,0x8,0xB,0x5,0x6,0x4,0xE,0xA,0x2,0xC,0x1,0x7,0x9,0xF,0xD,0x0, // K7
0x1,0x2,0x3,0xE,0x6,0xD,0xB,0x8,0xF,0xA,0xC,0x5,0x7,0x9,0x0,0x4, // K8
};
public static byte[] GetHash(byte[] data) {
byte[] hash = new byte[32];
Gost3411Digest digest = new Gost3411Digest(sBoxParam);
digest.BlockUpdate(data, 0, data.Length);
digest.DoFinal(hash, 0);
return hash;
}
public static byte[] GetSignature(ICipherParameters privKey, byte[] data, bool isLE) {
Dstu4145Signer dstuSigner = new Dstu4145Signer();
dstuSigner.Init(true, privKey);
BigInteger[] rs = dstuSigner.GenerateSignature(GetHash(data));
byte[] r = rs[0].ToByteArray();
byte[] s = rs[1].ToByteArray();
if (isLE) {
reverseBytes(r);
reverseBytes(s);
}
return r.Concat(s).ToArray();
}
private static byte[] ToDER(Asn1Encodable inObj) {
MemoryStream bOut = new MemoryStream();
DerOutputStream aOut = new DerOutputStream(bOut);
aOut.WriteObject(inObj);
return bOut.ToArray();
}
private static byte[] FileToByteArray(string filename) {
byte[] buf = null;
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(filename).Length;
buf = br.ReadBytes((int)numBytes);
return buf;
}
private static void reverseBytes(byte[] bytes) {
byte tmp;
for (int i = 0; i < bytes.Length / 2; i++) {
tmp = bytes[i];
bytes[i] = bytes[bytes.Length - 1 - i];
bytes[bytes.Length - 1 - i] = tmp;
}
}
public static void Main(String[] args) {
Asn1Sequence keyInfo = Asn1Sequence.GetInstance(
new Asn1InputStream(
FileToByteArray(args[0])
).ReadObject()
);
IEnumerator e = keyInfo.GetEnumerator();
e.MoveNext();
BigInteger version = ((DerInteger)e.Current).Value;
e.MoveNext();
AlgorithmIdentifier algId = AlgorithmIdentifier.GetInstance(e.Current);
if (!algId.Algorithm.Equals(UAObjectIdentifiers.dstu4145le)) {
return;
}
bool isLE = algId.Algorithm.Equals(UAObjectIdentifiers.dstu4145le);
e.MoveNext();
Asn1OctetString asnD = Asn1OctetString.GetInstance(e.Current);
byte[] secretD = asnD.GetOctets();
if (isLE) {
reverseBytes(secretD);
}
BigInteger d = new BigInteger(secretD);
DSTU4145Params dstuParams = DSTU4145Params.GetInstance(algId.Parameters);
ECDomainParameters ecDomain;
if (dstuParams.isNamedCurve()) {
DerObjectIdentifier curveOid = dstuParams.getNamedCurve();
ecDomain = DSTU4145NamedCurves.getByOID(curveOid);
}
else {
DSTU4145ECBinary binary = dstuParams.getECBinary();
byte[] b_bytes = binary.getB();
if (isLE) {
reverseBytes(b_bytes);
}
DSTU4145BinaryField field = binary.getField();
ECCurve curve = new F2mCurve(field.getM(), field.getK1(), field.getK2(), field.getK3(), binary.getA(), new BigInteger(1, b_bytes));
byte[] g_bytes = binary.getG();
if (isLE) {
reverseBytes(g_bytes);
}
ecDomain = new ECDomainParameters(curve, DSTU4145PointEncoder.decodePoint(curve, g_bytes), binary.getN());
}
ICipherParameters privKey = new ECPrivateKeyParameters(d, ecDomain);
byte[] data = Encoding.ASCII.GetBytes("Hello World!");
byte[] hash = GetHash(data);
CmsProcessable content = new CmsProcessableByteArray(data);
Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
Asn1EncodableVector signerInfos = new Asn1EncodableVector();
Asn1EncodableVector certificates = new Asn1EncodableVector();
Asn1EncodableVector signedAttrsV = new Asn1EncodableVector();
Asn1Set certrevlist = null;
Asn1Set signedAttr = null;
Asn1Set unsignedAttr = null;
digestAlgs.Add(new AlgorithmIdentifier(UAObjectIdentifiers.gost34311));
byte[] certBytes = FileToByteArray(args[1]);
X509CertificateStructure certAsn = X509CertificateStructure.GetInstance(
new Asn1InputStream(certBytes).ReadObject()
);
X509Certificate cert = new X509Certificate(certAsn);
certificates.Add(certAsn);
IssuerSerial issuerSerial = new IssuerSerial(
new GeneralNames(new GeneralName(cert.IssuerDN)),
new DerInteger(cert.SerialNumber)
);
EssCertIDv2 certidv2 = new EssCertIDv2(
new AlgorithmIdentifier(UAObjectIdentifiers.gost34311),
GetHash(certBytes),
issuerSerial
);
signedAttrsV.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(
PkcsObjectIdentifiers.IdAASigningCertificateV2,
new DerSet(new DerSequence(new DerSequence(certidv2)))
));
signedAttrsV.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(
CmsAttributes.ContentType,
new DerSet(CmsObjectIdentifiers.Data)
));
signedAttrsV.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(
CmsAttributes.MessageDigest,
new DerSet(new DerOctetString(hash))
));
signedAttrsV.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(
PkcsObjectIdentifiers.Pkcs9AtSigningTime,
new DerSet(new DerUtcTime(new DateTime()))
));
signedAttr = new DerSet(signedAttrsV);
byte[] signatureRS = GetSignature(privKey, ToDER(signedAttr), isLE);
SignerIdentifier sid = new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert));
signerInfos.Add(
new Org.BouncyCastle.Asn1.Cms.SignerInfo(
sid,
new AlgorithmIdentifier(UAObjectIdentifiers.gost34311),
signedAttr,
new AlgorithmIdentifier(UAObjectIdentifiers.dstu4145le),
new DerOctetString(signatureRS),
unsignedAttr
)
);
Asn1OctetString octs = new DerOctetString(data);
Org.BouncyCastle.Asn1.Cms.ContentInfo encInfo = new Org.BouncyCastle.Asn1.Cms.ContentInfo(CmsObjectIdentifiers.Data, octs);
Org.BouncyCastle.Asn1.Cms.SignedData sd = new Org.BouncyCastle.Asn1.Cms.SignedData(
new DerSet(digestAlgs),
encInfo,
new DerSet(certificates),
certrevlist,
new DerSet(signerInfos)
);
Org.BouncyCastle.Asn1.Cms.ContentInfo contentInfo = new Org.BouncyCastle.Asn1.Cms.ContentInfo(CmsObjectIdentifiers.SignedData, sd);
CmsSignedData signedCMS = new CmsSignedData(content, contentInfo);
byte[] coded = ToDER(signedCMS.ContentInfo);
using (BinaryWriter writer = new BinaryWriter(
File.Open(args[2], FileMode.Create)
)) {
writer.Write(coded);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment