private static ReadOnlySpan <byte> GetOctetStringContents( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, out int bytesConsumed, ref byte[]?rented, Span <byte> tmpSpace = default) { Debug.Assert(rented == null); if (TryReadPrimitiveOctetStringCore( source, ruleSet, expectedTag, universalTagNumber, out int?contentLength, out int headerLength, out ReadOnlySpan <byte> contents, out bytesConsumed)) { return(contents); } // If we get here, the tag was appropriate, but the encoding was constructed. // Guaranteed long enough contents = source.Slice(headerLength); int tooBig = contentLength ?? SeekEndOfContents(contents, ruleSet); if (tmpSpace.Length > 0 && tooBig > tmpSpace.Length) { bool isIndefinite = contentLength == null; tooBig = CountConstructedOctetString(contents, ruleSet, isIndefinite); } if (tooBig > tmpSpace.Length) { rented = CryptoPool.Rent(tooBig); tmpSpace = rented; } if (TryCopyConstructedOctetStringContents( Slice(source, headerLength, contentLength), ruleSet, tmpSpace, contentLength == null, out int bytesRead, out int bytesWritten)) { bytesConsumed = headerLength + bytesRead; return(tmpSpace.Slice(0, bytesWritten)); } Debug.Fail("TryCopyConstructedOctetStringContents failed with a pre-allocated buffer"); throw new AsnContentException(); }
internal static ReadOnlyMemory <byte> GetContent( ReadOnlyMemory <byte> wrappedContent, string contentType) { // Read the input. // // PKCS7's id-data is written in both PKCS#7 and CMS as an OCTET STRING wrapping // the arbitrary bytes, so the OCTET STRING must always be present. // // For other types, CMS says to always write an OCTET STRING, and to put the properly // encoded data within it. // PKCS#7 originally ommitted the OCTET STRING wrapper for this model, so this is the // dynamic adapter. // // See https://tools.ietf.org/html/rfc5652#section-5.2.1 byte[]? rented = null; int bytesWritten = 0; try { AsnReader reader = new AsnReader(wrappedContent, AsnEncodingRules.BER); if (reader.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> inner)) { return(inner); } rented = CryptoPool.Rent(wrappedContent.Length); if (!reader.TryReadOctetString(rented, out bytesWritten)) { Debug.Fail($"TryCopyOctetStringBytes failed with an array larger than the encoded value"); throw new CryptographicException(); } return(rented.AsSpan(0, bytesWritten).ToArray()); } catch (Exception) when(contentType != Oids.Pkcs7Data) { } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } finally { if (rented != null) { CryptoPool.Return(rented, bytesWritten); } } // PKCS#7 encoding for something other than id-data. Debug.Assert(contentType != Oids.Pkcs7Data); return(wrappedContent); }
private static byte[]? DecryptKey( RSA?privateKey, RSAEncryptionPadding encryptionPadding, ReadOnlySpan <byte> encryptedKey, out Exception?exception) { if (privateKey == null) { exception = new CryptographicException(SR.Cryptography_Cms_Signing_RequiresPrivateKey); return(null); } #if NETCOREAPP || NETSTANDARD2_1 byte[]? cek = null; int cekLength = 0; try { cek = CryptoPool.Rent(privateKey.KeySize / 8); if (!privateKey.TryDecrypt(encryptedKey, cek, encryptionPadding, out cekLength)) { Debug.Fail("TryDecrypt wanted more space than the key size"); exception = new CryptographicException(); return(null); } exception = null; return(new Span <byte>(cek, 0, cekLength).ToArray()); } catch (CryptographicException e) { exception = e; return(null); } finally { if (cek != null) { CryptoPool.Return(cek, cekLength); } } #else try { exception = null; return(privateKey.Decrypt(encryptedKey.ToArray(), encryptionPadding)); } catch (CryptographicException e) { exception = e; return(null); } #endif }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <remarks> /// Allows the caller to handle the encoding of the passphrase to bytes. /// </remarks> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="rawOldPassPhrase">The current password for the key.</param> /// <param name="rawNewPassPhrase">The new password for the key.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, ReadOnlySpan <byte> rawOldPassPhrase, ReadOnlySpan <byte> rawNewPassPhrase) { if (key == null) { throw new ArgumentNullException(nameof(key)); } if (key.IsPrivateKeyEmpty) { throw new PgpException("no private key in this SecretKey - public key present only."); } byte[] rawKeyData = CryptoPool.Rent(key.keyPacket.KeyBytes.Length - key.keyPacket.PublicKeyLength + 0x20); try { S2kBasedEncryption.DecryptSecretKey( rawOldPassPhrase, key.keyPacket.KeyBytes.AsSpan(key.keyPacket.PublicKeyLength), rawKeyData, out int rawKeySize, key.keyPacket.Version); // Use the default S2K parameters var s2kParameters = new S2kParameters(); var newKeyData = new byte[S2kBasedEncryption.GetEncryptedLength(s2kParameters, rawKeySize, key.keyPacket.Version) + key.keyPacket.PublicKeyLength]; key.keyPacket.KeyBytes.AsSpan(0, key.keyPacket.PublicKeyLength).CopyTo(newKeyData); S2kBasedEncryption.EncryptSecretKey( rawNewPassPhrase, s2kParameters, rawKeyData.AsSpan(0, rawKeySize), newKeyData.AsSpan(key.keyPacket.PublicKeyLength), key.keyPacket.Version); SecretKeyPacket newKeyPacket; if (key.keyPacket is SecretSubkeyPacket) { newKeyPacket = new SecretSubkeyPacket(key.Algorithm, key.CreationTime, newKeyData); } else { newKeyPacket = new SecretKeyPacket(key.Algorithm, key.CreationTime, newKeyData); } return(new PgpSecretKey(newKeyPacket, key)); } finally { CryptoPool.Return(rawKeyData); } }
private static byte[]? DecryptContent( ReadOnlyMemory <byte> encryptedContent, byte[] cek, AlgorithmIdentifierAsn contentEncryptionAlgorithm, out Exception?exception) { exception = null; int encryptedContentLength = encryptedContent.Length; byte[]? encryptedContentArray = CryptoPool.Rent(encryptedContentLength); try { encryptedContent.CopyTo(encryptedContentArray); using (SymmetricAlgorithm alg = OpenAlgorithm(contentEncryptionAlgorithm)) { ICryptoTransform decryptor; try { decryptor = alg.CreateDecryptor(cek, alg.IV); } catch (ArgumentException ae) { // Decrypting or deriving the symmetric key with the wrong key may still succeed // but produce a symmetric key that is not the correct length. throw new CryptographicException(SR.Cryptography_Cms_InvalidSymmetricKey, ae); } using (decryptor) { // If we extend this library to accept additional algorithm providers // then a different array pool needs to be used. Debug.Assert(alg.GetType().Assembly == typeof(Aes).Assembly); return(decryptor.OneShot( encryptedContentArray, 0, encryptedContentLength)); } } } catch (CryptographicException e) { exception = e; return(null); } finally { CryptoPool.Return(encryptedContentArray, encryptedContentLength); encryptedContentArray = null; } }
private static void SortContents(byte[] buffer, int start, int end) { Debug.Assert(buffer != null); Debug.Assert(end >= start); int len = end - start; if (len == 0) { return; } // Since BER can read everything and the reader does not mutate data // just use a BER reader for identifying the positions of the values // within this memory segment. // // Since it's not mutating, any restrictions imposed by CER or DER will // still be maintained. var reader = new AsnReader(new ReadOnlyMemory <byte>(buffer, start, len), AsnEncodingRules.BER); List <(int, int)> positions = new List <(int, int)>(); int pos = start; while (reader.HasData) { ReadOnlyMemory <byte> encoded = reader.ReadEncodedValue(); positions.Add((pos, encoded.Length)); pos += encoded.Length; } Debug.Assert(pos == end); var comparer = new ArrayIndexSetOfValueComparer(buffer); positions.Sort(comparer); byte[] tmp = CryptoPool.Rent(len); pos = 0; foreach ((int offset, int length) in positions) { Buffer.BlockCopy(buffer, offset, tmp, pos, length); pos += length; } Debug.Assert(pos == len); Buffer.BlockCopy(tmp, 0, buffer, start, len); CryptoPool.Return(tmp, len); }
public TailEndCryptoTransform(ICryptoTransform innerTransform, int tailEndSize) { int rollingBufferSize = innerTransform.CanTransformMultipleBlocks ? 128 * innerTransform.InputBlockSize : innerTransform.InputBlockSize + tailEndSize; this.innerTransform = innerTransform; this.tailEndSize = tailEndSize; this.rollingBuffer = new ArraySegment <byte>(CryptoPool.Rent(rollingBufferSize), 0, rollingBufferSize); this.rollingBufferOffset = 0; }
/// <summary>Add a PBE encryption method to the encrypted object.</summary> public void AddMethod(ReadOnlySpan <char> passPhrase, PgpHashAlgorithm s2kDigest) { byte[] rawPassPhrase = Array.Empty <byte>(); try { rawPassPhrase = CryptoPool.Rent(Encoding.UTF8.GetByteCount(passPhrase)); int bytesWritten = Encoding.UTF8.GetBytes(passPhrase, rawPassPhrase); AddMethod(rawPassPhrase.AsSpan(0, bytesWritten), s2kDigest); } finally { CryptoPool.Return(rawPassPhrase); } }
public static byte[] DecodeOctetStringCore(byte[] encodedOctets) { // Read using BER because the CMS specification says the encoding is BER. AsnReader reader = new AsnReader(encodedOctets, AsnEncodingRules.BER); const int ArbitraryStackLimit = 256; Span <byte> tmp = stackalloc byte[ArbitraryStackLimit]; // Use stackalloc 0 so data can later hold a slice of tmp. ReadOnlySpan <byte> data = stackalloc byte[0]; byte[] poolBytes = null; try { if (!reader.TryReadPrimitiveOctetStringBytes(out var contents)) { if (reader.TryCopyOctetStringBytes(tmp, out int bytesWritten)) { data = tmp.Slice(0, bytesWritten); } else { poolBytes = CryptoPool.Rent(reader.PeekContentBytes().Length); if (!reader.TryCopyOctetStringBytes(poolBytes, out bytesWritten)) { Debug.Fail("TryCopyOctetStringBytes failed with a provably-large-enough buffer"); throw new CryptographicException(); } data = new ReadOnlySpan <byte>(poolBytes, 0, bytesWritten); } } else { data = contents.Span; } reader.ThrowIfNotEmpty(); return(data.ToArray()); } finally { if (poolBytes != null) { CryptoPool.Return(poolBytes, data.Length); } } }
public void Encrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> plaintext, Span <byte> ciphertext, Span <byte> tag, ReadOnlySpan <byte> associatedData = default) { CheckParameters(plaintext, ciphertext, nonce, tag); var realNonce = CryptoPool.Rent(16); var stretch = CryptoPool.Rent(24); var offset = CryptoPool.Rent(16); var checksum = CryptoPool.Rent(16); var tmp = CryptoPool.Rent(16); CryptographicOperations.ZeroMemory(checksum.AsSpan(0, 16)); try { int bottom = nonce[^ 1] & 0x3f;
public AesOcb(ReadOnlySpan <byte> key) { this.aes = Aes.Create(); this.aes.Key = key.ToArray(); this.aes.Mode = CipherMode.ECB; this.aes.Padding = PaddingMode.None; l_star = CryptoPool.Rent(16); l_dollar = CryptoPool.Rent(16); encryptor = aes.CreateEncryptor(); CryptographicOperations.ZeroMemory(l_star.AsSpan(0, 16)); encryptor.TransformBlock(l_star, 0, 16, l_star, 0); Double(l_star, l_dollar); }
private static unsafe string HexDump(byte *bytes, uint length, int bytesPerLine = 16) { var lengthInt = (int)length; using (var pool = CryptoPool.Rent <byte>(lengthInt)) { var managedBytes = pool.Memory.Slice(0, lengthInt); var span = new Span <byte>(bytes, lengthInt); span.CopyTo(managedBytes.Span); return(HexDump(managedBytes.Span, bytesPerLine)); } }
private unsafe DiffieHellmanKey ExportKey(string keyType, DateTimeOffset?expiry) { int status = 0; status = BCryptExportKey(hPrivateKey, IntPtr.Zero, keyType, null, 0, out int pcbResult, 0); ThrowIfNotNtSuccess(status); DiffieHellmanKey key; using (var rental = CryptoPool.Rent <byte>(pcbResult)) { var output = rental.Memory; fixed(byte *pbOutput = &MemoryMarshal.GetReference(output.Span)) { status = BCryptExportKey(hPrivateKey, IntPtr.Zero, keyType, pbOutput, pcbResult, out pcbResult, 0); ThrowIfNotNtSuccess(status); BCRYPT_DH_KEY_BLOB *param = (BCRYPT_DH_KEY_BLOB *)pbOutput; key = new DiffieHellmanKey() { KeyLength = param->header.cbKey, Algorithm = param->header.cbKey < 256 ? KeyAgreementAlgorithm.DiffieHellmanModp2 : KeyAgreementAlgorithm.DiffieHellmanModp14, Type = param->header.dwMagic == BCRYPT_DH_PRIVATE_MAGIC ? AsymmetricKeyType.Private : AsymmetricKeyType.Public, CacheExpiry = expiry }; } var export = output.Span.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER)); key.Modulus = Copy(export.Slice(0, key.KeyLength)); key.Generator = Copy(export.Slice(key.KeyLength, key.KeyLength)); key.Public = Copy(export.Slice(key.KeyLength + key.KeyLength, key.KeyLength)); if (key.Type == AsymmetricKeyType.Private) { key.Private = Copy(export.Slice(key.KeyLength + key.KeyLength + key.KeyLength, key.KeyLength)); } key.Factor = Copy(Factor); } return(key); }
public static ReadOnlyMemory <byte> Decrypt( ReadOnlyMemory <byte> ciphertext, ReadOnlyMemory <byte> key, ReadOnlyMemory <byte> iv ) { if (!CalculateLength(ciphertext.Length, out int padSize, out int maxLength)) { return(ciphertext); } using (var rental = CryptoPool.Rent <byte>(maxLength)) { var aes = CryptoPal.Platform.Aes(); Memory <byte> ciphertextRented; if (padSize == BlockSize) { ciphertextRented = rental.Memory.Slice(0, ciphertext.Length); ciphertext.CopyTo(ciphertextRented); } else { var depadded = Depad(ciphertext, padSize); var decryptedPad = aes.Decrypt(depadded, key, iv); ciphertextRented = rental.Memory.Slice(0, maxLength); ciphertext.CopyTo(ciphertextRented); decryptedPad.Slice(decryptedPad.Length - padSize) .CopyTo( ciphertextRented.Slice(ciphertext.Length) ); } if (ciphertext.Length >= TwoBlockSizes) { SwapLastTwoBlocks(ciphertextRented.Span); } return(aes.Decrypt(ciphertextRented, key, iv).Slice(0, ciphertext.Length)); } }
private void WriteConstructedCerCharacterString(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan <char> str, int size) { Debug.Assert(size > AsnReader.MaxCERSegmentSize); byte[] tmp = CryptoPool.Rent(size); int written = encoding.GetBytes(str, tmp); if (written != size) { Debug.Fail( $"Encoding produced different answer for GetByteCount ({size}) and GetBytes ({written})"); throw new InvalidOperationException(); } WriteConstructedCerOctetString(tag, tmp.AsSpan(0, size)); CryptoPool.Return(tmp, size); }
/// <summary> /// Reads a NamedBitList from <paramref name="source"/> with a specified tag under /// the specified encoding rules. /// </summary> /// <param name="source">The buffer containing encoded data.</param> /// <param name="ruleSet">The encoding constraints to use when interpreting the data.</param> /// <param name="bytesConsumed"> /// When this method returns, the total number of bytes for the encoded value. /// This parameter is treated as uninitialized. /// </param> /// <param name="expectedTag"> /// The tag to check for before reading, or <see langword="null"/> for the default tag (Universal 3). /// </param> /// <returns> /// The bits from the encoded value. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="ruleSet"/> is not defined. /// </exception> /// <exception cref="AsnContentException"> /// the next value does not have the correct tag. /// /// -or- /// /// the length encoding is not valid under the current encoding rules. /// /// -or- /// /// the contents are not valid under the current encoding rules. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for /// the method. /// </exception> /// <remarks> /// The bit alignment performed by this method is to interpret the most significant bit /// in the first byte of the value as bit 0, /// with bits increasing in value until the least significant bit of the first byte, proceeding /// with the most significant bit of the second byte, and so on. /// This means that the number used in an ASN.1 NamedBitList construction is the index in the /// return value. /// </remarks> public static BitArray ReadNamedBitList( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, out int bytesConsumed, Asn1Tag?expectedTag = null) { Asn1Tag actualTag = ReadEncodedValue(source, ruleSet, out _, out int contentLength, out _); // Get the last ArgumentException out of the way before we rent arrays if (expectedTag != null) { CheckExpectedTag(actualTag, expectedTag.Value, UniversalTagNumber.BitString); } // The number of interpreted bytes is at most contentLength - 1, just ask for contentLength. byte[] rented = CryptoPool.Rent(contentLength); if (!TryReadBitString( source, rented, ruleSet, out int unusedBitCount, out int consumed, out int written, expectedTag)) { Debug.Fail("TryReadBitString failed with an over-allocated buffer"); throw new InvalidOperationException(); } int validBitCount = checked (written * 8 - unusedBitCount); Span <byte> valueSpan = rented.AsSpan(0, written); ReverseBitsPerByte(valueSpan); BitArray ret = new BitArray(rented); CryptoPool.Return(rented, written); // Trim off all of the unnecessary parts. ret.Length = validBitCount; bytesConsumed = consumed; return(ret); }
private ReadOnlySpan <byte> GetOctetStringContents( Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, out int bytesRead, ref byte[]?rented, Span <byte> tmpSpace = default) { Debug.Assert(rented == null); if (TryReadPrimitiveOctetStringBytes( expectedTag, out Asn1Tag actualTag, out int?contentLength, out int headerLength, out ReadOnlySpan <byte> contentsOctets, universalTagNumber)) { bytesRead = headerLength + contentsOctets.Length; return(contentsOctets); } Debug.Assert(actualTag.IsConstructed); ReadOnlySpan <byte> source = Slice(_data, headerLength, contentLength); bool isIndefinite = contentLength == null; int octetStringLength = CountConstructedOctetString(source, isIndefinite); if (tmpSpace.Length < octetStringLength) { rented = CryptoPool.Rent(octetStringLength); tmpSpace = rented; } CopyConstructedOctetString( source, tmpSpace, isIndefinite, out int localBytesRead, out int bytesWritten); Debug.Assert(bytesWritten == octetStringLength); bytesRead = headerLength + localBytesRead; return(tmpSpace.Slice(0, bytesWritten)); }
public override ReadOnlyMemory <byte> Encrypt(ReadOnlyMemory <byte> data, KerberosKey kerberosKey, KeyUsage usage) { var ke = this.GetOrDeriveKey(kerberosKey, usage, KeyDerivationMode.Ke); ReadOnlyMemory <byte> confounder; if (this.Confounder.Length > 0) { confounder = this.Confounder; } else { confounder = this.GenerateRandomBytes(this.ConfounderSize); } var concatLength = confounder.Length + data.Length; using (var cleartextPool = CryptoPool.Rent <byte>(concatLength)) { var cleartext = cleartextPool.Memory.Slice(0, concatLength); Concat(confounder.Span, data.Span, cleartext); var encrypted = AESCTS.Encrypt( cleartext, ke, AllZerosInitVector ); var checksumDataLength = AllZerosInitVector.Length + encrypted.Length; using (var checksumDataRented = CryptoPool.Rent <byte>(checksumDataLength)) { var checksumData = checksumDataRented.Memory.Slice(0, checksumDataLength); Concat(AllZerosInitVector.Span, encrypted.Span, checksumData); var checksum = this.MakeChecksum(checksumData, kerberosKey, usage, KeyDerivationMode.Ki, this.ChecksumSize); return(Concat(encrypted.Span, checksum.Span)); } } }
/// <summary> /// Builds an <see cref="X500DistinguishedName" /> that represents the encoded attributes. /// </summary> /// <returns> /// An <see cref="X500DistinguishedName" /> that represents the encoded attributes. /// </returns> public X500DistinguishedName Build() { _writer.Reset(); using (_writer.PushSequence()) { for (int i = _encodedComponents.Count - 1; i >= 0; i--) { _writer.WriteEncodedValue(_encodedComponents[i]); } } byte[] rented = CryptoPool.Rent(_writer.GetEncodedLength()); int encoded = _writer.Encode(rented); X500DistinguishedName name = new X500DistinguishedName(rented.AsSpan(0, encoded)); CryptoPool.Return(rented, clearSize: 0); // Distinguished Names do not contain sensitive information. return(name); }
public CFBMode(byte[] iv, IBlockTransform blockTransform, bool encryption, int paddingSizeInBytes) : base(iv, blockTransform.BlockSizeInBytes, paddingSizeInBytes) { if (iv == null) { throw new ArgumentNullException(nameof(iv)); } if (iv.Length != blockTransform.BlockSizeInBytes) { throw new ArgumentOutOfRangeException(nameof(iv)); } this.FR = CryptoPool.Rent(iv.Length); this.FRE = CryptoPool.Rent(iv.Length); iv.CopyTo(this.FR, 0); this.blockTransform = blockTransform; this.encryption = encryption; }
public byte[] ExportPrivateKey( ReadOnlySpan <byte> passwordBytes, S2kParameters s2kParameters) { ECParameters ecParameters = new ECParameters(); byte[] secretPart = Array.Empty <byte>(); try { ecParameters = ecdh.ExportParameters(true); if (ecdh is X25519) { Array.Reverse(ecParameters.D !); } int secretSize = MPInteger.GetMPEncodedLength(ecParameters.D !); secretPart = CryptoPool.Rent(secretSize); MPInteger.TryWriteInteger(ecParameters.D, secretPart, out var _); int encryptedSecretLength = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize); int estimatedLength = 32 /* OID */ + MPInteger.GetMPEncodedLength(ecParameters.Q.X !, ecParameters.Q.Y !) + 1 /* EC Point type */ + 4 /* KDF Parameters */ + encryptedSecretLength; var destination = new byte[estimatedLength]; WriteOpenPgpECParameters(ecParameters, destination, out int bytesWritten); WriteKDFParameters(destination.AsSpan(bytesWritten)); S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(bytesWritten + 4)); return(destination.AsSpan(0, bytesWritten + 4 + encryptedSecretLength).ToArray()); } finally { CryptoPool.Return(secretPart); if (ecParameters.D != null) { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
protected override ReadOnlyMemory <byte> String2Key(ReadOnlyMemory <byte> password, ReadOnlyMemory <byte> salt, ReadOnlyMemory <byte> param) { /* * iter_count = string-to-key parameter, default is decimal 32768 * saltp = enctype-name | 0x00 | salt * tkey = random-to-key(PBKDF2(passphrase, saltp, iter_count, keylength)) * base-key = random-to-key(KDF-HMAC-SHA2(tkey, "kerberos", keylength)) * * where "kerberos" is the octet-string 0x6B65726265726F73. */ var encLength = this.encTypeNameBytes.Length; var saltpLen = encLength + 1 + salt.Length; using (var saltpRented = CryptoPool.Rent <byte>(saltpLen)) { var saltp = saltpRented.Memory.Slice(0, saltpLen); this.encTypeNameBytes.CopyTo(saltp); salt.CopyTo(saltp.Slice(encLength + 1)); var iterationsLen = param.Length == 0 ? 4 : param.Length; using (var iterationsRented = CryptoPool.Rent <byte>(iterationsLen)) { var iterations = iterationsRented.Memory.Slice(0, iterationsLen); if (param.Length == 0) { DefaultIterations.CopyTo(iterations); } else { param.CopyTo(iterations); } return(base.String2Key(password, saltp, iterations)); } } }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="oldPassPhrase">The current password for the key.</param> /// <param name="newPassPhrase">The new password for the key.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, ReadOnlySpan <char> oldPassPhrase, ReadOnlySpan <char> newPassPhrase) { int oldPassPhraseByteCount = Encoding.UTF8.GetByteCount(oldPassPhrase); int newPassPhraseByteCount = Encoding.UTF8.GetByteCount(newPassPhrase); byte[] passphraseBuffer = CryptoPool.Rent(oldPassPhraseByteCount + newPassPhraseByteCount); try { Encoding.UTF8.GetBytes(oldPassPhrase, passphraseBuffer); Encoding.UTF8.GetBytes(newPassPhrase, passphraseBuffer.AsSpan(oldPassPhraseByteCount)); return(CopyWithNewPassword(key, passphraseBuffer.AsSpan(0, oldPassPhraseByteCount), passphraseBuffer.AsSpan(oldPassPhraseByteCount, newPassPhraseByteCount))); } finally { CryptoPool.Return(passphraseBuffer, oldPassPhraseByteCount + newPassPhraseByteCount); } }
private static ArraySegment <byte> EncodeKeys(AsnWriter tmpWriter, SafeBagAsn[] keyBags, int keyCount) { Debug.Assert(tmpWriter.GetEncodedLength() == 0); tmpWriter.PushSequence(); for (int i = 0; i < keyCount; i++) { keyBags[i].Encode(tmpWriter); } tmpWriter.PopSequence(); ReadOnlySpan <byte> encodedKeys = tmpWriter.EncodeAsSpan(); int length = encodedKeys.Length; byte[] keyBuf = CryptoPool.Rent(length); encodedKeys.CopyTo(keyBuf); tmpWriter.Reset(); return(new ArraySegment <byte>(keyBuf, 0, length)); }
private static string GetStringProvParam( SafeProvOrNCryptKeyHandle handle, CryptProvParam dwParam, ref Span <byte> buf, ref byte[] rented, int clearLen) { int len = buf.Length; if (!Interop.Advapi32.CryptGetProvParam(handle, dwParam, buf, ref len)) { if (len > buf.Length) { if (rented != null) { CryptoPool.Return(rented, clearLen); } rented = CryptoPool.Rent(len); buf = rented; len = rented.Length; } else { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } if (!Interop.Advapi32.CryptGetProvParam(handle, dwParam, buf, ref len)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } } unsafe { fixed(byte *asciiPtr = &MemoryMarshal.GetReference(buf)) { return(Marshal.PtrToStringAnsi((IntPtr)asciiPtr, len)); } } }
public static ReadOnlyMemory <byte> Encrypt( ReadOnlyMemory <byte> plainText, ReadOnlyMemory <byte> key, ReadOnlyMemory <byte> iv ) { if (!CalculateLength(plainText.Length, out int padSize, out int maxLength)) { return(plainText); } using (var rental = CryptoPool.Rent <byte>(maxLength)) { Memory <byte> plaintextRented; if (padSize == BlockSize) { plaintextRented = rental.Memory.Slice(0, plainText.Length); plainText.CopyTo(plaintextRented); } else { plaintextRented = rental.Memory.Slice(0, maxLength); plainText.CopyTo(plaintextRented); plaintextRented.Span.Slice(plaintextRented.Length - padSize).Fill(0); } var aes = CryptoPal.Platform.Aes(); var encrypted = aes.Encrypt(plaintextRented, key, iv); if (plainText.Length >= TwoBlockSizes) { SwapLastTwoBlocks(encrypted.Span); } return(encrypted.Slice(0, plainText.Length)); } }
private static byte[]? DecryptContent( ReadOnlyMemory <byte> encryptedContent, byte[] cek, AlgorithmIdentifierAsn contentEncryptionAlgorithm, out Exception?exception) { exception = null; int encryptedContentLength = encryptedContent.Length; byte[]? encryptedContentArray = CryptoPool.Rent(encryptedContentLength); try { encryptedContent.CopyTo(encryptedContentArray); using (SymmetricAlgorithm alg = OpenAlgorithm(contentEncryptionAlgorithm)) using (ICryptoTransform decryptor = alg.CreateDecryptor(cek, alg.IV)) { // If we extend this library to accept additional algorithm providers // then a different array pool needs to be used. Debug.Assert(alg.GetType().Assembly == typeof(Aes).Assembly); return(decryptor.OneShot( encryptedContentArray, 0, encryptedContentLength)); } } catch (CryptographicException e) { exception = e; return(null); } finally { CryptoPool.Return(encryptedContentArray, encryptedContentLength); encryptedContentArray = null; } }
private static Memory <byte> PseudoRandomPlus(ReadOnlyMemory <byte> key, ReadOnlyMemory <byte> pepper, KerberosCryptoTransformer handler) { // PRF+(protocol key, octet string) -> (octet string) // PRF+(key, shared-info) := pseudo-random(key, 1 || shared-info ) || // pseudo-random(key, 2 || shared-info ) || // pseudo-random(key, 3 || shared-info ) || ... using (var pool = CryptoPool.Rent <byte>(pepper.Length + 1)) { Memory <byte> input = pool.Memory.Slice(0, pepper.Length + 1); int prfSize = handler.BlockSize; int iterations = handler.KeySize / prfSize; if (handler.KeySize % prfSize > 0) { iterations++; } input.Span[0] = 1; pepper.CopyTo(input.Slice(1)); Memory <byte> result = new byte[prfSize * iterations]; for (var i = 0; i < iterations; i++) { handler.PseudoRandomFunction(key, input) .Slice(0, prfSize) .CopyTo(result.Slice(i * prfSize)); input.Span[0]++; } return(result); } }
public override ReadOnlyMemory <byte> Encrypt(ReadOnlyMemory <byte> data, KerberosKey kerberosKey, KeyUsage usage) { var Ke = GetOrDeriveKey(kerberosKey, usage); var confounder = GenerateRandomBytes(ConfounderSize); var concatLength = confounder.Length + data.Length; using (var cleartextPool = CryptoPool.Rent <byte>(concatLength)) { var cleartext = Concat(confounder.Span, data.Span, cleartextPool.Memory.Slice(0, concatLength)); var encrypted = AESCTS.Encrypt( cleartext, Ke, AllZerosInitVector ); var checksum = MakeChecksum(cleartext, kerberosKey, usage, KeyDerivationMode.Ki, ChecksumSize); return(Concat(encrypted.Span, checksum.Span)); } }
/// <summary> /// Purge the ticket cache of the provided Logon Id. Note that the value 0 zero is treated as the current users Logon Id. /// </summary> /// <param name="luid">The Logon Id of the cache to be purged.</param> public unsafe void PurgeTicketCache(long luid = 0) { var purgeRequest = new KERB_PURGE_TKT_CACHE_EX_REQUEST { MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbPurgeTicketCacheExMessage, Flags = 1, LogonId = luid }; var bufferSize = Marshal.SizeOf(typeof(KERB_PURGE_TKT_CACHE_EX_REQUEST)); using (var pool = CryptoPool.Rent <byte>(bufferSize)) { var buffer = pool.Memory.Slice(0, bufferSize); fixed(void *pBuffer = &MemoryMarshal.GetReference(buffer.Span)) { Marshal.StructureToPtr(purgeRequest, (IntPtr)pBuffer, false); this.LsaCallAuthenticationPackage(pBuffer, bufferSize); } } }