The ISO/IEC 9796-2 standard is a digital signature scheme that supports message recovery. This will thus reduce storage requirements of a message and its digital signature. Overall, we can use RSA or ElGamal as an engine for the signature, and where the message is limited in size to the number of bytes in the modulus.
ISO9796d2 Signing and Message Recovery using Bouncy Castle and C# |
Method
With RSA, we have two prime numbers (\(p\) and \(q\)), and compute the modulus (\(N\)):
\(N=pq\)
We then pick an encryption key value (\(e=0x010001\)) and then compute:
\(d=e^{-1} \pmod \phi\))
and where:
\(\phi=(p-1)(q-1)\)
The public key is then \((e,N)\) and the private key is \((d,N)\). To encrypt a message (\(M\)), we create a cipher:
\(c=M^e \pmod N\)
and then decrypt with:
\(M=c^d \pmod N\).
Additional parameters
With this we have two prime numbers (\(p\) and \(q\)), and compute the modulus (\(N\)):
\(N=pq\)
We then pick an encryption key value (\(e=0x010001\)) and then compute:
\(d=e^{-1} \pmod \phi\))
and where:
\(\phi=(p-1)(q-1)\)
The public key is then \((e,N)\) and the private key is \((d,N)\). To encrypt a message (\(M\)), we create a cipher:
\(c=M^e \pmod N\)
and then decrypt with:
\(M=c^d \pmod N\)
The key pair thus contains \(e, N, d, p\) and \(q\) for a key pair of \((e,N)\) and \((d,N)\). It also has the values of \(dQ\), \(dP\) and \(InvQ\). The value of \(dQ\) is:
\(dQ = d \pmod {q-1}\)
and \(dP\) is:
\(dP = d \pmod {p-1}\)
and we also have:
\(InvQ = q^{-1} \pmod p\)
We can use the values of \(dQ\), \(dP\) and \(InvQ\) to reduce the computational resource for the decrpytion. This uses Chinese remainder theory with:
\(c=M^e \pmod N\)
To decrypt, we use less complex exponents:
\(m_1=c^{dQ} \pmod {q}\)
\(m_2=c^{dP} \pmod {p}\)
and then compute:
\(h=InvQ \times (m_1-m_2) \pmod p\)
The recovered message (\(m\)) is then:
\(m=m_2+h \times q \pmod N\)
Hashing
With ISO/IEC 9796-2, we hash with:
\(\mu(m)={6A}_{16} || m[1] || HASH(m) || {BC}_{16}\)
and which produces a fixed bit length and where m[1] is the message.
Code
First we install the Bouncy Castle library:
dotnet add package BouncyCastle.Cryptography
Next some code:
namespace ECCurves { using Org.BouncyCastle.Security; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto; class Program { static void Main(string[] args) { var size="512"; var msg="Hello"; if (args.Length >0) msg=args[0]; if (args.Length >1) size=args[1]; try { var mess=System.Text.Encoding.ASCII.GetBytes(msg); var s =Convert.ToInt32(size); RsaKeyPairGenerator pGen = new RsaKeyPairGenerator(); pGen.Init(new KeyGenerationParameters(new SecureRandom(), s)); var keyPair = pGen.GenerateKeyPair(); // Create signature var signer = new Iso9796d2Signer(new RsaEngine(),new Sha256Digest()) ; var privateKey = (RsaPrivateCrtKeyParameters) keyPair.Private; var publicKey = keyPair.Public; signer.Init(true, privateKey); signer.BlockUpdate(mess,0,mess.Length); var sig=signer.GenerateSignature() ; // Verify signature signer = new Iso9796d2Signer(new RsaEngine(),new Sha256Digest()) ; signer.Init(false, publicKey); var rtn=signer.VerifySignature(sig); var recovered_message=signer.GetRecoveredMessage(); Console.WriteLine("== Algol: {0} ",signer.AlgorithmName); Console.WriteLine("== Message: {0} ",msg); Console.WriteLine("\n== Signature === "); Console.WriteLine("== sig={0} ",Convert.ToHexString(sig)); Console.WriteLine("== Verified: {0} ",rtn); Console.WriteLine("== Recovered message: {0} ", System.Text.Encoding.ASCII.GetString(recovered_message)); RsaPrivateCrtKeyParameters priv = ((RsaPrivateCrtKeyParameters)keyPair.Private); Console.WriteLine("\n\nKey size:\t{0}",size); Console.WriteLine("RSA N:\t{0}",priv.Modulus); Console.WriteLine("RSA d:\t{0}",priv.Exponent); Console.WriteLine(" p:\t{0}",priv.P); Console.WriteLine(" q:\t{0}",priv.Q); Console.WriteLine("RSA e:\t{0}",priv.PublicExponent); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run showing the cipher text, and the public and private key is:
== Algol: SHA-256withISO9796-2S1 == Message: Hello == Signature === == sig=0F67495F09107DB16C22009267E4D93495935751B224F204E229CF8ECB205F23E68200B9DB74966161AA078C4126402C3ADAACC613A8E89368083D7007F264CC == Verified: True == Recovered message: Hello Key size: 512 RSA N: 8032801254117746017350197996930384525180731627489937515710753143869609268686122142985183158277800017168062065146301705954803873511012437017995300803530819 RSA d: 4006349973186439800358839233206662095950684107327919230469498644080351303247067429549066913924215634780466858198903620213260354992610098243678695935494893 p: 96082685356563064852212178407265493323580971201586825863151019996074628623671 q: 83603005310561442084602853988500545348168949262608678917722245502914378767189 RSA e: 65537
and for 2K modulus:
== Algol: SHA-256withISO9796-2S1 == Message: Hello == Signature === == sig=75E5DCF940ECC8EE47E59E3D9F14E34A1DC54B578A8CF9ECF3D95C9DB3B785FBFC1B8912B36B2322C6633028DB7F26D28FDF6FC5236AD5AA65FDFFE1415C63BB1D3AA0C04F04E82F9826F9A21235BC67AFD4BBDB739C0441F735499442F45983B659120A2FD57DBD840563BD3DFB527F3B10FBA55324C6F13F11D3A5CCCB103B47B2F1EA0CD804F701C6B21792B87927E894532CBEA02346FE389E80EF9BE7B4E63829EF54311BACB211637A55F21A6D00FF7E90CB789EB771304E219C877049E6287E7D27CFD819673F9FC4BF532939E817BA53B8CAD1B7340E0BDA7008A34A6B8ECACD20E43297CFFBBA4EA93DDDDDB9EBBBD5516DB087EB1A066D3BA3D038 == Verified: True == Recovered message: Hello Key size: 2048 RSA N: 27389803845623543343340096511575379448158551989514283196855648800771134384884854789899920892815054819199570059825277817329152486568926702925876443033385721356244758654744096597037343121383961570756045739008432145587756160762070651794535993537435693356563704041976937733622878821722318511918282924031249284713291529458788293285844465506725528481984767918113879704682732609514471832591749032015697195546021733569918892154697997442837675878722602173590440193946653924846791118924610334904161997243567586140234194054997566921017973101229062711512920654579092032262294486519260084422478040100361135550053387975411211572613 RSA d: 235363604260092143769031707566243005618525278780355023173106380868327975257045445918773193506014592861221770989796129781027527076604064190677369274887494475036368869224967835984225659823601950418808404799603003443197552698513910036604607886036374383558978785413430765831799104675220903845084654470761023882298273432390241605880664819976517786903690314832348971137854595782522738803009681458238367249955760350299210726163550568494604179739397138211776156862177867047074315282576460356810087501168449412343269258603491933188383658740516693152816175374923002306739666565267756946030472611729843743815415459633472287233 p: 175597504181740571281444463615080281879049939177136466806011553429636722221847816886716328184200592523966879696170148198708257092286966201170798631295260337384348526412305198294786287797903246795460493795075290685495058594605731506998343393832005968395016729753086295739171948213837146870536672779046260599041 q: 155980598774772676798362315437681937352562317792639322881320090475141000397402558019952383561257661772392900246783640411757342797833913130776834828807266556984592221383189749090708580891518137858995356250871579297907466428119793141496914605145436814663138909140332438629445629817973347474845126599740730869893 RSA e: 65537