/// <summary> /// Secret key operation. Decrypts biCipher with the keydata /// in the given secret key packet. /// </summary> /// <param name="biCipher">The ciphertext that is about to /// be decrypted</param> /// <param name="skpKey">The secret key packet with the key /// material for the decryption</param> /// <param name="strPassphrase">The passphrase for the /// keymaterial</param> /// <returns>The decrypted ciphertext.</returns> /// <remarks>No remarks.</remarks> public override BigInteger Decrypt(BigInteger[] biCipher, SecretKeyPacket skpKey, string strPassphrase) { RSA_Secret_Key skey = new RSA_Secret_Key(); skey = ParseSecretKey(skpKey, strPassphrase); //check if someone mangled with the key if (!CheckKey(skey)) throw(new Exception("This key does not fullfill the requirements of a valid RSA key. Please check if someone messed with your keys!")); if ((skey.d == 0) || (skey.n == 0)) throw new System.ArgumentException("This is not a valid secret key"); BigInteger biPlain = biCipher[0].modPow(skey.d, skey.n); return biPlain; }
/// <summary> /// Secret key operation. Decrypts biCipher with the keydata /// in the given secret key packet. /// </summary> /// <param name="biInput">The ciphertext that is about to /// be decrypted</param> /// <param name="skpKey">The secret key packet with the key /// material for the decryption</param> /// <param name="strPassphrase">The passphrase for the /// keymaterial</param> /// <returns>The decrypted ciphertext.</returns> /// <remarks>No remarks.</remarks> public override BigInteger Decrypt(BigInteger[] biInput, SecretKeyPacket skpKey, string strPassphrase) { BigInteger[] biKeyMaterial = skpKey.GetDecryptedKeyMaterial(strPassphrase); EG_Secret_Key eskKey = new EG_Secret_Key(); eskKey.x = biKeyMaterial[0]; eskKey.p = skpKey.PublicKey.KeyMaterial[0]; eskKey.g = skpKey.PublicKey.KeyMaterial[1]; eskKey.y = skpKey.PublicKey.KeyMaterial[2]; if (biInput.Length != 2) throw new ArgumentException("biInput is not an ElGamal encrypted Packet"); BigInteger B = biInput[0]; BigInteger c = biInput[1]; BigInteger z = B.modPow(eskKey.x, eskKey.p).modInverse(eskKey.p); BigInteger output = (z * c) % eskKey.p; return output; }
private DSA_Secret_Key ParseSecretKey(SecretKeyPacket skpKey, string strPassphrase) { DSA_Secret_Key dskKey = new DSA_Secret_Key(); dskKey.p = skpKey.PublicKey.KeyMaterial[0]; dskKey.q = skpKey.PublicKey.KeyMaterial[1]; dskKey.g = skpKey.PublicKey.KeyMaterial[2]; dskKey.y = skpKey.PublicKey.KeyMaterial[3]; BigInteger[] biSecretKeyMaterial = skpKey.GetDecryptedKeyMaterial(strPassphrase); dskKey.x = biSecretKeyMaterial[0]; return dskKey; }
/// <summary> /// Secret key operation. Signs biHash with the keydata /// in the given secret key packet. /// </summary> /// <param name="biHash">The hash value of a message that is about to /// be signed</param> /// <param name="skpKey">The secret key packet with the key /// material for the signature</param> /// <param name="strPassphrase">The passphrase for the /// keymaterial</param> /// <returns>The signed hash as array of biginteger. Only return[0] /// contains a value: the signed hash.</returns> /// <remarks>No remarks</remarks> public override BigInteger[] Sign(BigInteger biHash, SecretKeyPacket skpKey, string strPassphase) { DSA_Secret_Key dskKey = new DSA_Secret_Key(); dskKey = ParseSecretKey(skpKey, strPassphase); //check if the key has been mangled with if (!CheckKey(dskKey)) throw(new Exception("This key does not fullfill the requirements of a valid DSA key. Please check if someone messed with your keys!")); //if (biHash == null) // throw new ArgumentNullException(); // (a) Select a random secret integer k; 0 < k < q. BigInteger k = new BigInteger(); k = BigInteger.genRandom(160); while (k >= dskKey.q) k = BigInteger.genRandom(160); // (b) Compute r = ( k mod p) mod q BigInteger r = (dskKey.g.modPow (k, dskKey.p)) % dskKey.q; // (c) Compute k -1 mod q (e.g., using Algorithm 2.142). // (d) Compute s = k -1 fh(m) +arg mod q. BigInteger s = (k.modInverse (dskKey.q) * (biHash + dskKey.x * r)) % dskKey.q; BigInteger[] biReturn = new BigInteger[2]; biReturn[0] = r; biReturn[1] = s; return biReturn; }
/// <summary> /// Signes the data given as parameter with the given secret key. /// The given password has to fit the given key. /// </summary> /// <remarks> /// <para>The function calculates a message digest over the given signature /// data and signes the digest with the given key.</para> /// <para>The results of the signature operation are directly stored /// in the Signature property of this class.</para> /// </remarks> /// <param name="bSignedData">The data that is to be signed.</param> /// <param name="skpKey">The key that is to sign the data</param> /// <param name="strPassphrase">The passphrase that is neccessary to /// decrypt the given key.</param> public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase) { System.Security.Cryptography.HashAlgorithm haSigner; AsymmetricCipher acSigner; this.SignatureAlgorithm = skpKey.PublicKey.Algorithm; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: haSigner = System.Security.Cryptography.MD5.Create(); break; case HashAlgorithms.SHA1: haSigner = System.Security.Cryptography.SHA1.Create(); break; default: throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!")); } switch (this.SignatureAlgorithm) { case AsymAlgorithms.DSA: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA(); break; case AsymAlgorithms.RSA_Encrypt_Sign: case AsymAlgorithms.RSA_Sign_Only: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA(); break; default: throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!")); } byte[] bSignature = new byte[0]; int iCounter = 0; if (this.Version <= SignaturePacketVersionNumbers.v3) { bSignature = new byte[5]; bSignature[iCounter++] = (byte)this.SignatureType; long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks)/10000000; bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lTime & 0xFF); } else { // Add Issuer KeyID Subpacket if it's not there. try { ulong lTestForKeyID = this.KeyID; } catch (Exception) { SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket(); sspIssuerKeyID.Type = SignatureSubPacketTypes.IssuerKeyID; sspIssuerKeyID.KeyID = this.lKeyID; this.AddSubPacket(sspIssuerKeyID, true); } // Add TimeCreated Subpacket if it's not there. try { this.FindSignatureCreationTime(); } catch (Exception) { SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; this.AddSubPacket(sspCreationTime, true); } //Hashed Subpackets Length int lHashedSubPacketLength = 0; for (int i=0; i<this.HashedSubPackets.Length; i++) { lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length; } bSignature = new byte[lHashedSubPacketLength + 12]; bSignature[iCounter++] = 4; // Version bSignature[iCounter++] = (byte)this.SignatureType; bSignature[iCounter++] = (byte)this.SignatureAlgorithm; bSignature[iCounter++] = (byte)this.HashAlgorithm; //Hashed bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF); for (int i=0; i<this.HashedSubPackets.Length; i++) { byte[] bSubPacket = this.HashedSubPackets[i].Generate(); Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length); iCounter += bSubPacket.Length; } //Final Trailer of 6 bytes bSignature[iCounter++] = 0x04; bSignature[iCounter++] = 0xFF; bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 24) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 16) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength+6) >> 8) & 0xFF); bSignature[iCounter++] = (byte)((lHashedSubPacketLength+6) & 0xFF); } byte[] bData = new byte[bSignedData.Length + bSignature.Length]; Array.Copy(bSignedData, bData, bSignedData.Length); Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length); byte[] bHash = haSigner.ComputeHash(bData); BigInteger biHash = new BigInteger(bHash); //PKCS1 Encode the hash if (this.SignatureAlgorithm != AsymAlgorithms.DSA) { // We encode the MD in this way: // 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) // PAD consists of FF bytes. byte[] bASN = new byte[0]; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: bASN = new byte[] {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; break; case HashAlgorithms.SHA1: bASN = new byte[] {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; break; } int iFrameSize = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8; byte[] bFrame = new byte[iFrameSize]; int iASNCounter = 0; bFrame[iASNCounter++] = 0; bFrame[iASNCounter++] = 1; int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3; for (int i=0; i<iFFLength; i++) bFrame[iASNCounter++] = 0xFF; bFrame[iASNCounter++] = 0; Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length); iASNCounter += bASN.Length; Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length); biHash = new BigInteger(bFrame); } sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]); biSignature = acSigner.Sign(biHash, skpKey, strPassphrase); this.bIsUpdated = true; }
public override BigInteger[] Sign(BigInteger biHash, SecretKeyPacket spkKey, string strPassphrase) { throw new System.NotImplementedException("Signatures with ElGamal keys are not yet implemented!"); }
private RSA_Secret_Key ParseSecretKey(SecretKeyPacket skpKey, string strPassphrase) { RSA_Secret_Key rskKey = new RSA_Secret_Key(); rskKey.n = skpKey.PublicKey.KeyMaterial[0]; rskKey.e = skpKey.PublicKey.KeyMaterial[1]; BigInteger[] biSecretKeyMaterial = skpKey.GetDecryptedKeyMaterial(strPassphrase); rskKey.d = biSecretKeyMaterial[0]; rskKey.p = biSecretKeyMaterial[1]; rskKey.q = biSecretKeyMaterial[2]; rskKey.u = biSecretKeyMaterial[3]; return rskKey; }
/// <summary> /// Generates a subkey for the specified primary key pair /// </summary> /// <param name="iKeySize">size of the subkey</param> /// <param name="strPassphrase">passphrase for the primar secret key</param> /// <param name="PrimaryKeyID">primary key pair keyID</param> /// <param name="expirationTime">expiration time for the subkey (new DateTime(0) == never)</param> /// <param name="isRevocableSubkey">is revocable?</param> public void GenerateSubkey(int iKeySize, string strPassphrase, ulong PrimaryKeyID, DateTime expirationTime, bool isRevocableSubkey) { if (iKeySize % 1024 != 0) throw new Exception("Keysize must be a 1024 multiple"); TransportablePublicKey tpkKey = this.PublicRing.Find(PrimaryKeyID,false); TransportableSecretKey tskKey = this.SecretRing.Find(PrimaryKeyID); System.Security.Cryptography.RandomNumberGenerator rngRand; BigInteger[][] biEncryptionKey = GenerateElGamalEncryptionKey(iKeySize); PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(tpkKey.PrimaryKey, tskKey.PrimaryKey, strPassphrase, expirationTime, isRevocableSubkey); tpkKey.SubKeys.Add(cpsEncryptionKey); this.PublicRing.AddPublicKey(tpkKey); tskKey.SubKeys.Add(skpEncryptionKey); this.SecretRing.AddSecretKey(tskKey); }
/// <summary> /// Parses a single packet out of the given binary /// data. Even if there are more than one packets in the byte /// array, only the first packet is returned. /// </summary> /// <param name="bBinaryData">A byte array containing a set /// of OpenPGP packets</param> /// <returns>Returns an single OpenPGP packets</returns> /// <remarks>No remarks</remarks> public virtual Packet ParsePacket(byte[] bBinaryData) { Packet pReturnPacket = new Packet(); if ((bBinaryData[0] & 0xC0) == 0xC0) { pfFormat = PacketFormats.New; } else if ((bBinaryData[0] & 0xC0) == 0x80) { pfFormat = PacketFormats.Old; } else { throw(new ArgumentException("This is not a valid OpenPGP Packet")); } if (pfFormat == PacketFormats.New) { int iBinaryDataPos = 1; ctContent = (ContentTypes)(bBinaryData[0] & 0x3F); lLength = bBinaryData[1]; bBody = new byte[0]; int iHeaderLength = 1; //partial body lengths while ((lLength > 223) && (lLength < 255)) { iBinaryDataPos += 1; iHeaderLength++; int lPartialBody = 1 << ((int)(lLength & 0x1F)); int lOldLength = 0; if (bBody.Length > 0) { byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lPartialBody]; bOldBody.CopyTo(bBody, 0); lOldLength = bBody.Length; } else { bBody = new byte[lPartialBody]; } Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - lPartialBody, lPartialBody); lLength = bBinaryData[iBinaryDataPos + lPartialBody]; iBinaryDataPos += lPartialBody; } //partial bodies must end with a normal header! if (lLength < 192) { iHeaderLength++; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 2); iBinaryDataPos = 1; } byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos + 1, bBody, bBody.Length - (int)lLength, (int)lLength); } else if ((lLength > 191) && (lLength < 224)) { iHeaderLength += 2; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 3); iBinaryDataPos = 1; } lLength = ((bBinaryData[iBinaryDataPos++] - 192) << 8) + bBinaryData[iBinaryDataPos++] + 192; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } else if (lLength == 255) { iHeaderLength += 5; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 6); iBinaryDataPos = 1; } lLength = (bBinaryData[iBinaryDataPos++] << 24) ^ (bBinaryData[iBinaryDataPos++] << 16) ^ (bBinaryData[iBinaryDataPos++] << 8) ^ bBinaryData[iBinaryDataPos++]; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } } else { ctContent = (ContentTypes)((bBinaryData[0] & 0x3C) >> 2); switch (bBinaryData[0] & 0x03) { case 0: lLength = bBinaryData[1]; bHeader = new byte[2]; break; case 1: lLength = (bBinaryData[1] << 8) ^ (bBinaryData[2]); bHeader = new byte[3]; break; case 2: lLength = (bBinaryData[1] << 16) ^ (bBinaryData[2] << 8) ^ (bBinaryData[3]); bHeader = new byte[4]; break; case 3: throw new System.NotSupportedException("Packets of indetermined length are not supported due to security considerations!"); default: throw new System.ApplicationException("This is not a valid Packet!"); } bBody = new byte[lLength]; Array.Copy(bBinaryData, 0, bHeader, 0, bHeader.Length); Array.Copy(bBinaryData, bHeader.Length, bBody, 0, (int)lLength); } this.bIsUpdated = false; switch (ctContent) { case ContentTypes.AsymSessionKey: pReturnPacket = new AsymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Compressed: pReturnPacket = new CompressedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.LiteralData: pReturnPacket = new LiteralDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Marker: pReturnPacket = new Packet(this); //We can savly ignore Marker packets! //MessageBox.Show("This is a marker packet. It is not yet supported."); break; case ContentTypes.OnePassSignature: pReturnPacket = new OnePassSignaturePacket(this); //System.Windows.Forms.MessageBox.Show("This is a One Pass Signature Packet. It is not yet supported"); break; //Content is Public Key Packet case ContentTypes.PublicKey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; //Content is Public Subkey Packet. Same format as Public Key Packet case ContentTypes.PublicSubkey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretKey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretSubkey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Signature: pReturnPacket = new SignaturePacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymEncrypted: pReturnPacket = new SymmetricallyEncryptedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymSessionKey: pReturnPacket = new SymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Trust: pReturnPacket = new Packet(this); //throw new Exception("This is a Trust Packet. It is not yet supported"); break; case ContentTypes.UserID: pReturnPacket = new UserIDPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; default: pReturnPacket = new Packet(this); //throw new Exception("Sorry, but this is a packet I don't know about!"); break; } pReturnPacket.bIsUpdated = false; return pReturnPacket; }
/// <summary> /// Decrypts the session key stored in the EncryptedSessionKey /// property and saves the decrypted key in the EncodedSessionKey /// property. /// </summary> /// <remarks>This function also calls DecodeSessionKey so that the /// decrypted and decoded sessionkey is stored in the /// SessionKey property.</remarks> /// <param name="tskKey">A transportable secret key that is used to /// decrypt the encrypted session key.</param> /// <param name="strPassphrase">The passphrase used to decrypt the /// encrypted key material of the given transportable secret /// key.</param> public void DecryptSessionKey(TransportableSecretKey tskKey, string strPassphrase) { AsymmetricCipher acCipher = new RSA(); switch (aaPublicAlgorithm) { case AsymAlgorithms.ElGama_Encrypt_Sign: case AsymAlgorithms.ElGamal_Encrypt_Only: acCipher = new ElGamal(); break; case AsymAlgorithms.RSA_Encrypt_Only: case AsymAlgorithms.RSA_Encrypt_Sign: acCipher = new RSA(); break; default: throw new System.Exception("The chosen public key algorithm is not yet implemented!"); } bool bFound = false; SecretKeyPacket skpKey = new SecretKeyPacket(); IEnumerator ieSubkeys = tskKey.SubKeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { if (!(ieSubkeys.Current is SecretKeyPacket)) throw new System.Exception("Expected a secret key packet, but did not find one!"); skpKey = (SecretKeyPacket)ieSubkeys.Current; if (skpKey.PublicKey.KeyID == lKeyID) { bFound = true; continue; } } // check if the message was encrypted with the primary key if (!bFound) { if (tskKey.PrimaryKey.PublicKey.KeyID == lKeyID) { skpKey = tskKey.PrimaryKey; } else { //theoretically we should never see this exception, as //encrytped message makes sure we only get fitting secret //keys, but just in case someone calls this directly, we //throw an exception throw new System.Exception("No fitting secret key found!"); } } BigInteger biKey = acCipher.Decrypt(this.biEncryptedSessionKey, skpKey, strPassphrase); this.bEncodedSessionKey = biKey.getBytes(); DecodeSessionKey(); }
/// <summary> /// Signes the data given as parameter with the given secret key. /// The given password has to fit the given key. /// </summary> /// <remarks> /// <para>The function calculates a message digest over the given signature /// data and signes the digest with the given key.</para> /// <para>The results of the signature operation are directly stored /// in the Signature property of this class.</para> /// </remarks> /// <param name="bSignedData">The data that is to be signed.</param> /// <param name="skpKey">The key that is to sign the data</param> /// <param name="strPassphrase">The passphrase that is neccessary to /// decrypt the given key.</param> public void Sign(byte[] bSignedData, SecretKeyPacket skpKey, string strPassphrase) { System.Security.Cryptography.HashAlgorithm haSigner; AsymmetricCipher acSigner; this.SignatureAlgorithm = skpKey.PublicKey.Algorithm; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: haSigner = System.Security.Cryptography.MD5.Create(); break; case HashAlgorithms.SHA1: haSigner = System.Security.Cryptography.SHA1.Create(); break; default: throw(new System.Exception("Currently only MD5 and SHA1 are implemented as hash algorithms!")); } switch (this.SignatureAlgorithm) { case AsymAlgorithms.DSA: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.DSA(); break; case AsymAlgorithms.RSA_Encrypt_Sign: case AsymAlgorithms.RSA_Sign_Only: acSigner = new SharpPrivacy.SharpPrivacyLib.Cipher.RSA(); break; default: throw(new System.Exception("Currently only DSA and RSA are implemented as signature algorithms!")); } byte[] bSignature = new byte[0]; int iCounter = 0; if (this.Version <= SignaturePacketVersionNumbers.v3) { bSignature = new byte[5]; bSignature[iCounter++] = (byte)this.SignatureType; long lTime = (dtTimeCreated.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000; bSignature[iCounter++] = (byte)((lTime >> 24) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 16) & 0xFF); bSignature[iCounter++] = (byte)((lTime >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lTime & 0xFF); } else { // Add Issuer KeyID Subpacket if it's not there. try { ulong lTestForKeyID = this.KeyID; } catch (Exception) { SignatureSubPacket sspIssuerKeyID = new SignatureSubPacket(); sspIssuerKeyID.Type = SignatureSubPacketTypes.IssuerKeyID; sspIssuerKeyID.KeyID = this.lKeyID; this.AddSubPacket(sspIssuerKeyID, true); } // Add TimeCreated Subpacket if it's not there. try { this.FindSignatureCreationTime(); } catch (Exception) { SignatureSubPacket sspCreationTime = new SignatureSubPacket(); sspCreationTime.Type = SignatureSubPacketTypes.SignatureCreationTime; sspCreationTime.TimeCreated = DateTime.Now; this.AddSubPacket(sspCreationTime, true); } //Hashed Subpackets Length int lHashedSubPacketLength = 0; for (int i = 0; i < this.HashedSubPackets.Length; i++) { lHashedSubPacketLength += this.HashedSubPackets[i].Generate().Length; } bSignature = new byte[lHashedSubPacketLength + 12]; bSignature[iCounter++] = 4; // Version bSignature[iCounter++] = (byte)this.SignatureType; bSignature[iCounter++] = (byte)this.SignatureAlgorithm; bSignature[iCounter++] = (byte)this.HashAlgorithm; //Hashed bSignature[iCounter++] = (byte)((lHashedSubPacketLength >> 8) & 0xFF); bSignature[iCounter++] = (byte)(lHashedSubPacketLength & 0xFF); for (int i = 0; i < this.HashedSubPackets.Length; i++) { byte[] bSubPacket = this.HashedSubPackets[i].Generate(); Array.Copy(bSubPacket, 0, bSignature, iCounter, bSubPacket.Length); iCounter += bSubPacket.Length; } //Final Trailer of 6 bytes bSignature[iCounter++] = 0x04; bSignature[iCounter++] = 0xFF; bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 24) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 16) & 0xFF); bSignature[iCounter++] = (byte)(((lHashedSubPacketLength + 6) >> 8) & 0xFF); bSignature[iCounter++] = (byte)((lHashedSubPacketLength + 6) & 0xFF); } byte[] bData = new byte[bSignedData.Length + bSignature.Length]; Array.Copy(bSignedData, bData, bSignedData.Length); Array.Copy(bSignature, 0, bData, bSignedData.Length, bSignature.Length); byte[] bHash = haSigner.ComputeHash(bData); BigInteger biHash = new BigInteger(bHash); //PKCS1 Encode the hash if (this.SignatureAlgorithm != AsymAlgorithms.DSA) { // We encode the MD in this way: // 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) // PAD consists of FF bytes. byte[] bASN = new byte[0]; switch (this.HashAlgorithm) { case HashAlgorithms.MD5: bASN = new byte[] { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; break; case HashAlgorithms.SHA1: bASN = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 }; break; } int iFrameSize = (skpKey.PublicKey.KeyMaterial[0].bitCount() + 7) / 8; byte[] bFrame = new byte[iFrameSize]; int iASNCounter = 0; bFrame[iASNCounter++] = 0; bFrame[iASNCounter++] = 1; int iFFLength = iFrameSize - bHash.Length - bASN.Length - 3; for (int i = 0; i < iFFLength; i++) { bFrame[iASNCounter++] = 0xFF; } bFrame[iASNCounter++] = 0; Array.Copy(bASN, 0, bFrame, iASNCounter, bASN.Length); iASNCounter += bASN.Length; Array.Copy(bHash, 0, bFrame, iASNCounter, bHash.Length); biHash = new BigInteger(bFrame); } sSignedHash16Bit = (ushort)((bHash[0] << 8) + bHash[1]); biSignature = acSigner.Sign(biHash, skpKey, strPassphrase); this.bIsUpdated = true; }
public abstract BigInteger[] Sign(BigInteger biHash, SecretKeyPacket spkKey, string strPassphrase);
public abstract BigInteger Decrypt(BigInteger[] biCipher, SecretKeyPacket spkKey, string strPassphrase);
/// <summary> /// Decryption is not supported for DSA. If you call this function, /// an Exception will be thrown. /// </summary> /// <remarks> /// Decryption is not supported for DSA. If you call this function, /// an Exception will be thrown. /// </remarks> public override BigInteger Decrypt(BigInteger[] biCipher, SecretKeyPacket spkKey, string strPassphrase) { throw(new Exception("The DSA cipher cannot be used for encryption/decryption")); }
/// <summary> /// Decrypts the session key stored in the EncryptedSessionKey /// property and saves the decrypted key in the EncodedSessionKey /// property. /// </summary> /// <remarks>This function also calls DecodeSessionKey so that the /// decrypted and decoded sessionkey is stored in the /// SessionKey property.</remarks> /// <param name="tskKey">A transportable secret key that is used to /// decrypt the encrypted session key.</param> /// <param name="strPassphrase">The passphrase used to decrypt the /// encrypted key material of the given transportable secret /// key.</param> public void DecryptSessionKey(TransportableSecretKey tskKey, string strPassphrase) { AsymmetricCipher acCipher = new RSA(); switch (aaPublicAlgorithm) { case AsymAlgorithms.ElGama_Encrypt_Sign: case AsymAlgorithms.ElGamal_Encrypt_Only: acCipher = new ElGamal(); break; case AsymAlgorithms.RSA_Encrypt_Only: case AsymAlgorithms.RSA_Encrypt_Sign: acCipher = new RSA(); break; default: throw new System.Exception("The chosen public key algorithm is not yet implemented!"); } bool bFound = false; SecretKeyPacket skpKey = new SecretKeyPacket(); IEnumerator ieSubkeys = tskKey.SubKeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { if (!(ieSubkeys.Current is SecretKeyPacket)) { throw new System.Exception("Expected a secret key packet, but did not find one!"); } skpKey = (SecretKeyPacket)ieSubkeys.Current; if (skpKey.PublicKey.KeyID == lKeyID) { bFound = true; continue; } } // check if the message was encrypted with the primary key if (!bFound) { if (tskKey.PrimaryKey.PublicKey.KeyID == lKeyID) { skpKey = tskKey.PrimaryKey; } else { //theoretically we should never see this exception, as //encrytped message makes sure we only get fitting secret //keys, but just in case someone calls this directly, we //throw an exception throw new System.Exception("No fitting secret key found!"); } } BigInteger biKey = acCipher.Decrypt(this.biEncryptedSessionKey, skpKey, strPassphrase); this.bEncodedSessionKey = biKey.getBytes(); DecodeSessionKey(); }
/// <summary> /// Generate a key pair /// </summary> /// <param name="iKeySize">Encription key size</param> /// <param name="strPassphrase">passhrase for the key pair</param> /// <param name="userID">primary user id</param> /// <param name="email">user email</param> /// <param name="notation">xml encoded user info</param> /// <param name="expirationTime">expiration date of the primary key (new DateTime(0) == never)</param> /// <param name="keyType">1: RSA/DSA 0:Elgamal/DSA(DEFAULT)</param> /// <param name="isRevocableKey">revocable?</param> /// <param name="isRevocableSubkey">revocable subkey?</param> public void GenerateKey(int iKeySize, string strPassphrase, string userID, string email, string notation, DateTime expirationTime, int keyType, bool isRevocableKey, bool isRevocableSubkey) { if(iKeySize % 1024 != 0) throw new Exception("Keysize must be a 1024 multiple"); System.Security.Cryptography.RandomNumberGenerator rngRand; // let's first create the encryption key BigInteger[][] biEncryptionKey; if (keyType == 1) { // it's a RSA/DSA key biEncryptionKey = GenerateRSAEncryptionKey(iKeySize); } else { // it's an elgamal/DSA key DEFAULF biEncryptionKey = GenerateElGamalEncryptionKey(iKeySize); } // now the signature key BigInteger[][] biSignatureKey = GenerateDSASignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); if (keyType == 0) { // it's an elgamal/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; } else if (keyType == 1) { // it's a RSA/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.RSA_Encrypt_Only; } pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = userID.Trim() + " <" + email.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); if (notation != null) { SignatureSubPacket sspNotation = new SignatureSubPacket(); sspNotation.Type = SignatureSubPacketTypes.NotationData; sspNotation.NotationName = "PersonalData"; sspNotation.NotationValue = notation; spSelfSig.AddSubPacket(sspNotation,false); } if (expirationTime.Ticks != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.KeyExpirationTime; sspExpiration.KeyExpirationTime = new DateTime(expirationTime.Ticks + (new DateTime(1970,1,2)).Ticks - pkpEncryptionKey.TimeCreated.Ticks); spSelfSig.AddSubPacket(sspExpiration, true); } if (!isRevocableKey) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocableKey; spSelfSig.AddSubPacket(sspRevocable, true); } SignatureSubPacket sspPrimaryUID = new SignatureSubPacket(); sspPrimaryUID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUID.Revocable = true; spSelfSig.AddSubPacket(sspPrimaryUID, true); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, expirationTime, isRevocableSubkey); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); this.PublicRing.AddPublicKey(tpkPublicKey); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.SecretRing.AddSecretKey(tskSecretKey); }
public void GenerateKey(string strName, string strEmail, string strKeyType, int iKeySize, long lExpiration, string strPassphrase) { if (strKeyType == "ElGamal/DSA") { System.Security.Cryptography.RandomNumberGenerator rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); // let's first create the encryption key BigInteger[][] biEncryptionKey = GenerateEncryptionKey(iKeySize); // now the signature key BigInteger[][] biSignatureKey = GenerateSignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = strName.Trim() + " <" + strEmail.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); if (lExpiration != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.SignatureExpirationTime; sspExpiration.SignatureExpirationTime = new DateTime(lExpiration); spSelfSig.AddSubPacket(sspExpiration, true); } cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, new DateTime(lExpiration), true); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.pkrKeyRing.AddPublicKey(tpkPublicKey); this.skrKeyRing.AddSecretKey(tskSecretKey); pkrKeyRing.Save(); skrKeyRing.Save(); // it's an RSA key } else if (strKeyType == "RSA") { } }
/// <summary> /// Parses a single packet out of the given binary /// data. Even if there are more than one packets in the byte /// array, only the first packet is returned. /// </summary> /// <param name="bBinaryData">A byte array containing a set /// of OpenPGP packets</param> /// <returns>Returns an single OpenPGP packets</returns> /// <remarks>No remarks</remarks> public virtual Packet ParsePacket(byte[] bBinaryData) { Packet pReturnPacket = new Packet(); if ((bBinaryData[0] & 0xC0) == 0xC0) { pfFormat = PacketFormats.New; } else if ((bBinaryData[0] & 0xC0) == 0x80) { pfFormat = PacketFormats.Old; } else { throw(new ArgumentException("This is not a valid OpenPGP Packet")); } if (pfFormat == PacketFormats.New) { int iBinaryDataPos = 1; ctContent = (ContentTypes)(bBinaryData[0] & 0x3F); lLength = bBinaryData[1]; bBody = new byte[0]; int iHeaderLength = 1; //partial body lengths while ((lLength > 223) && (lLength < 255)) { iBinaryDataPos += 1; iHeaderLength++; int lPartialBody = 1 << ((int)(lLength & 0x1F)); int lOldLength = 0; if (bBody.Length > 0) { byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lPartialBody]; bOldBody.CopyTo(bBody, 0); lOldLength = bBody.Length; } else { bBody = new byte[lPartialBody]; } Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - lPartialBody, lPartialBody); lLength = bBinaryData[iBinaryDataPos + lPartialBody]; iBinaryDataPos += lPartialBody; } //partial bodies must end with a normal header! if (lLength < 192) { iHeaderLength++; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 2); iBinaryDataPos = 1; } byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos + 1, bBody, bBody.Length - (int)lLength, (int)lLength); } else if ((lLength > 191) && (lLength < 224)) { iHeaderLength += 2; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 3); iBinaryDataPos = 1; } lLength = ((bBinaryData[iBinaryDataPos++] - 192) << 8) + bBinaryData[iBinaryDataPos++] + 192; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } else if (lLength == 255) { iHeaderLength += 5; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 6); iBinaryDataPos = 1; } lLength = (bBinaryData[iBinaryDataPos++] << 24) ^ (bBinaryData[iBinaryDataPos++] << 16) ^ (bBinaryData[iBinaryDataPos++] << 8) ^ bBinaryData[iBinaryDataPos++]; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } } else { ctContent = (ContentTypes)((bBinaryData[0] & 0x3C) >> 2); switch (bBinaryData[0] & 0x03) { case 0: lLength = bBinaryData[1]; bHeader = new byte[2]; break; case 1: lLength = (bBinaryData[1] << 8) ^ (bBinaryData[2]); bHeader = new byte[3]; break; case 2: lLength = (bBinaryData[1] << 16) ^ (bBinaryData[2] << 8) ^ (bBinaryData[3]); bHeader = new byte[4]; break; case 3: throw new System.NotSupportedException("Packets of indetermined length are not supported due to security considerations!"); default: throw new System.ApplicationException("This is not a valid Packet!"); } bBody = new byte[lLength]; Array.Copy(bBinaryData, 0, bHeader, 0, bHeader.Length); Array.Copy(bBinaryData, bHeader.Length, bBody, 0, (int)lLength); } this.bIsUpdated = false; switch (ctContent) { case ContentTypes.AsymSessionKey: pReturnPacket = new AsymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Compressed: pReturnPacket = new CompressedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.LiteralData: pReturnPacket = new LiteralDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Marker: pReturnPacket = new Packet(this); //We can savly ignore Marker packets! //MessageBox.Show("This is a marker packet. It is not yet supported."); break; case ContentTypes.OnePassSignature: pReturnPacket = new OnePassSignaturePacket(this); //System.Windows.Forms.MessageBox.Show("This is a One Pass Signature Packet. It is not yet supported"); break; //Content is Public Key Packet case ContentTypes.PublicKey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; //Content is Public Subkey Packet. Same format as Public Key Packet case ContentTypes.PublicSubkey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretKey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretSubkey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Signature: pReturnPacket = new SignaturePacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymEncrypted: pReturnPacket = new SymmetricallyEncryptedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymSessionKey: pReturnPacket = new SymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Trust: pReturnPacket = new Packet(this); //throw new Exception("This is a Trust Packet. It is not yet supported"); break; case ContentTypes.UserID: pReturnPacket = new UserIDPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; default: pReturnPacket = new Packet(this); //throw new Exception("Sorry, but this is a packet I don't know about!"); break; } pReturnPacket.bIsUpdated = false; return(pReturnPacket); }
/// <summary> /// Secret key operation. Signs biHash with the keydata /// in the given secret key packet. /// </summary> /// <param name="biHash">The hash value of a message that is about to /// be signed</param> /// <param name="skpKey">The secret key packet with the key /// material for the signature</param> /// <param name="strPassphrase">The passphrase for the /// keymaterial</param> /// <returns>The signed hash as array of biginteger. Only return[0] /// contains a value: the signed hash.</returns> /// <remarks>No remarks</remarks> public override BigInteger[] Sign(BigInteger biHash, SecretKeyPacket skpKey, string strPassphrase) { //Signing and encrypting is just the same BigInteger[] biHashArray = {biHash}; BigInteger biSignature = Decrypt(biHashArray, skpKey, strPassphrase); BigInteger[] biReturn = new BigInteger[1]; biReturn[0] = biSignature; return biReturn; }