mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
Compare commits
1 Commits
community/
...
aesgcm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02ad4adff5 |
@@ -1,5 +1,7 @@
|
|||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Javax.Crypto;
|
||||||
|
using Javax.Crypto.Spec;
|
||||||
using Org.BouncyCastle.Crypto;
|
using Org.BouncyCastle.Crypto;
|
||||||
using Org.BouncyCastle.Crypto.Digests;
|
using Org.BouncyCastle.Crypto.Digests;
|
||||||
using Org.BouncyCastle.Crypto.Generators;
|
using Org.BouncyCastle.Crypto.Generators;
|
||||||
@@ -33,5 +35,25 @@ namespace Bit.Droid.Services
|
|||||||
generator.Init(password, salt, iterations);
|
generator.Init(password, salt, iterations);
|
||||||
return ((KeyParameter)generator.GenerateDerivedMacParameters(keySize)).GetKey();
|
return ((KeyParameter)generator.GenerateDerivedMacParameters(keySize)).GetKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] AesGcmEncrypt(byte[] data, byte[] iv, byte[] key)
|
||||||
|
{
|
||||||
|
var secKey = new SecretKeySpec(key, "AES");
|
||||||
|
var cipher = Cipher.GetInstance("AES/GCM/NoPadding");
|
||||||
|
var gcmSpec = new GCMParameterSpec(128, iv);
|
||||||
|
cipher.Init(CipherMode.EncryptMode, secKey, gcmSpec);
|
||||||
|
var result = cipher.DoFinal(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] AesGcmDecrypt(byte[] data, byte[] iv, byte[] key)
|
||||||
|
{
|
||||||
|
var secKey = new SecretKeySpec(key, "AES");
|
||||||
|
var cipher = Cipher.GetInstance("AES/GCM/NoPadding");
|
||||||
|
var gcmSpec = new GCMParameterSpec(128, iv);
|
||||||
|
cipher.Init(CipherMode.DecryptMode, secKey, gcmSpec);
|
||||||
|
var result = cipher.DoFinal(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ namespace Bit.Core.Abstractions
|
|||||||
Task<byte[]> HashAsync(byte[] value, CryptoHashAlgorithm algorithm);
|
Task<byte[]> HashAsync(byte[] value, CryptoHashAlgorithm algorithm);
|
||||||
Task<byte[]> HmacAsync(byte[] value, byte[] key, CryptoHashAlgorithm algorithm);
|
Task<byte[]> HmacAsync(byte[] value, byte[] key, CryptoHashAlgorithm algorithm);
|
||||||
Task<bool> CompareAsync(byte[] a, byte[] b);
|
Task<bool> CompareAsync(byte[] a, byte[] b);
|
||||||
Task<byte[]> AesEncryptAsync(byte[] data, byte[] iv, byte[] key);
|
Task<byte[]> AesEncryptAsync(byte[] data, byte[] iv, byte[] key, AesMode mode);
|
||||||
Task<byte[]> AesDecryptAsync(byte[] data, byte[] iv, byte[] key);
|
Task<byte[]> AesDecryptAsync(byte[] data, byte[] iv, byte[] key, AesMode mode);
|
||||||
Task<byte[]> RsaEncryptAsync(byte[] data, byte[] publicKey, CryptoHashAlgorithm algorithm);
|
Task<byte[]> RsaEncryptAsync(byte[] data, byte[] publicKey, CryptoHashAlgorithm algorithm);
|
||||||
Task<byte[]> RsaDecryptAsync(byte[] data, byte[] privateKey, CryptoHashAlgorithm algorithm);
|
Task<byte[]> RsaDecryptAsync(byte[] data, byte[] privateKey, CryptoHashAlgorithm algorithm);
|
||||||
Task<byte[]> RsaExtractPublicKeyAsync(byte[] privateKey);
|
Task<byte[]> RsaExtractPublicKeyAsync(byte[] privateKey);
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ namespace Bit.Core.Abstractions
|
|||||||
public interface ICryptoPrimitiveService
|
public interface ICryptoPrimitiveService
|
||||||
{
|
{
|
||||||
byte[] Pbkdf2(byte[] password, byte[] salt, CryptoHashAlgorithm algorithm, int iterations);
|
byte[] Pbkdf2(byte[] password, byte[] salt, CryptoHashAlgorithm algorithm, int iterations);
|
||||||
|
byte[] AesGcmEncrypt(byte[] data, byte[] iv, byte[] key);
|
||||||
|
byte[] AesGcmDecrypt(byte[] data, byte[] iv, byte[] key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/Core/Enums/AesMode.cs
Normal file
8
src/Core/Enums/AesMode.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Bit.Core.Enums
|
||||||
|
{
|
||||||
|
public enum AesMode : byte
|
||||||
|
{
|
||||||
|
CBC = 0,
|
||||||
|
GCM = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
Rsa2048_OaepSha256_B64 = 3,
|
Rsa2048_OaepSha256_B64 = 3,
|
||||||
Rsa2048_OaepSha1_B64 = 4,
|
Rsa2048_OaepSha1_B64 = 4,
|
||||||
Rsa2048_OaepSha256_HmacSha256_B64 = 5,
|
Rsa2048_OaepSha256_HmacSha256_B64 = 5,
|
||||||
Rsa2048_OaepSha1_HmacSha256_B64 = 6
|
Rsa2048_OaepSha1_HmacSha256_B64 = 6,
|
||||||
|
AesGcm256_B64 = 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ namespace Bit.Core.Models.Domain
|
|||||||
Mac = encPieces[2];
|
Mac = encPieces[2];
|
||||||
break;
|
break;
|
||||||
case EncryptionType.AesCbc256_B64:
|
case EncryptionType.AesCbc256_B64:
|
||||||
|
case EncryptionType.AesGcm256_B64:
|
||||||
if (encPieces.Length != 2)
|
if (encPieces.Length != 2)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Domain
|
namespace Bit.Core.Models.Domain
|
||||||
@@ -30,22 +31,24 @@ namespace Bit.Core.Models.Domain
|
|||||||
}
|
}
|
||||||
|
|
||||||
Key = key;
|
Key = key;
|
||||||
EncType = encType.Value;
|
EncTypes.Add(encType.Value);
|
||||||
|
|
||||||
if (EncType == EncryptionType.AesCbc256_B64 && Key.Length == 32)
|
if (encType.Value == EncryptionType.AesCbc256_B64 && Key.Length == 32)
|
||||||
{
|
{
|
||||||
EncKey = Key;
|
EncKey = Key;
|
||||||
MacKey = null;
|
MacKey = null;
|
||||||
|
EncTypes.Add(EncryptionType.AesGcm256_B64);
|
||||||
}
|
}
|
||||||
else if (EncType == EncryptionType.AesCbc128_HmacSha256_B64 && Key.Length == 32)
|
else if (encType.Value == EncryptionType.AesCbc128_HmacSha256_B64 && Key.Length == 32)
|
||||||
{
|
{
|
||||||
EncKey = new ArraySegment<byte>(Key, 0, 16).ToArray();
|
EncKey = new ArraySegment<byte>(Key, 0, 16).ToArray();
|
||||||
MacKey = new ArraySegment<byte>(Key, 16, 16).ToArray();
|
MacKey = new ArraySegment<byte>(Key, 16, 16).ToArray();
|
||||||
}
|
}
|
||||||
else if (EncType == EncryptionType.AesCbc256_HmacSha256_B64 && Key.Length == 64)
|
else if (encType.Value == EncryptionType.AesCbc256_HmacSha256_B64 && Key.Length == 64)
|
||||||
{
|
{
|
||||||
EncKey = new ArraySegment<byte>(Key, 0, 32).ToArray();
|
EncKey = new ArraySegment<byte>(Key, 0, 32).ToArray();
|
||||||
MacKey = new ArraySegment<byte>(Key, 32, 32).ToArray();
|
MacKey = new ArraySegment<byte>(Key, 32, 32).ToArray();
|
||||||
|
EncTypes.Add(EncryptionType.AesGcm256_B64);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -69,9 +72,9 @@ namespace Bit.Core.Models.Domain
|
|||||||
public byte[] Key { get; set; }
|
public byte[] Key { get; set; }
|
||||||
public byte[] EncKey { get; set; }
|
public byte[] EncKey { get; set; }
|
||||||
public byte[] MacKey { get; set; }
|
public byte[] MacKey { get; set; }
|
||||||
public EncryptionType EncType { get; set; }
|
|
||||||
public string KeyB64 { get; set; }
|
public string KeyB64 { get; set; }
|
||||||
public string EncKeyB64 { get; set; }
|
public string EncKeyB64 { get; set; }
|
||||||
public string MacKeyB64 { get; set; }
|
public string MacKeyB64 { get; set; }
|
||||||
|
public HashSet<EncryptionType> EncTypes { get; set; } = new HashSet<EncryptionType>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ namespace Bit.Core.Services
|
|||||||
var iv = Convert.ToBase64String(encObj.Iv);
|
var iv = Convert.ToBase64String(encObj.Iv);
|
||||||
var data = Convert.ToBase64String(encObj.Data);
|
var data = Convert.ToBase64String(encObj.Data);
|
||||||
var mac = encObj.Mac != null ? Convert.ToBase64String(encObj.Mac) : null;
|
var mac = encObj.Mac != null ? Convert.ToBase64String(encObj.Mac) : null;
|
||||||
return new EncString(encObj.Key.EncType, data, iv, mac);
|
return new EncString(encObj.Type, data, iv, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null)
|
public async Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null)
|
||||||
@@ -491,7 +491,7 @@ namespace Bit.Core.Services
|
|||||||
macLen = encValue.Mac.Length;
|
macLen = encValue.Mac.Length;
|
||||||
}
|
}
|
||||||
var encBytes = new byte[1 + encValue.Iv.Length + macLen + encValue.Data.Length];
|
var encBytes = new byte[1 + encValue.Iv.Length + macLen + encValue.Data.Length];
|
||||||
Buffer.BlockCopy(new byte[] { (byte)encValue.Key.EncType }, 0, encBytes, 0, 1);
|
Buffer.BlockCopy(new byte[] { (byte)encValue.Type }, 0, encBytes, 0, 1);
|
||||||
Buffer.BlockCopy(encValue.Iv, 0, encBytes, 1, encValue.Iv.Length);
|
Buffer.BlockCopy(encValue.Iv, 0, encBytes, 1, encValue.Iv.Length);
|
||||||
if (encValue.Mac != null)
|
if (encValue.Mac != null)
|
||||||
{
|
{
|
||||||
@@ -561,6 +561,14 @@ namespace Bit.Core.Services
|
|||||||
ivBytes = new ArraySegment<byte>(encBytes, 1, 16).ToArray();
|
ivBytes = new ArraySegment<byte>(encBytes, 1, 16).ToArray();
|
||||||
ctBytes = new ArraySegment<byte>(encBytes, 17, encBytes.Length - 17).ToArray();
|
ctBytes = new ArraySegment<byte>(encBytes, 17, encBytes.Length - 17).ToArray();
|
||||||
break;
|
break;
|
||||||
|
case EncryptionType.AesGcm256_B64:
|
||||||
|
if (encBytes.Length < 13) // 1 + 12 + ctLength
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ivBytes = new ArraySegment<byte>(encBytes, 1, 12).ToArray();
|
||||||
|
ctBytes = new ArraySegment<byte>(encBytes, 13, encBytes.Length - 13).ToArray();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -589,16 +597,27 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
var obj = new EncryptedObject
|
var obj = new EncryptedObject
|
||||||
{
|
{
|
||||||
Key = await GetKeyForEncryptionAsync(key),
|
Key = await GetKeyForEncryptionAsync(key)
|
||||||
Iv = await _cryptoFunctionService.RandomBytesAsync(16)
|
|
||||||
};
|
};
|
||||||
obj.Data = await _cryptoFunctionService.AesEncryptAsync(data, obj.Iv, obj.Key.EncKey);
|
if (true)
|
||||||
if (obj.Key.MacKey != null)
|
|
||||||
{
|
{
|
||||||
var macData = new byte[obj.Iv.Length + obj.Data.Length];
|
obj.Type = EncryptionType.AesCbc256_HmacSha256_B64;
|
||||||
Buffer.BlockCopy(obj.Iv, 0, macData, 0, obj.Iv.Length);
|
obj.Iv = await _cryptoFunctionService.RandomBytesAsync(16);
|
||||||
Buffer.BlockCopy(obj.Data, 0, macData, obj.Iv.Length, obj.Data.Length);
|
obj.Data = await _cryptoFunctionService.AesEncryptAsync(data, obj.Iv, obj.Key.EncKey, AesMode.CBC);
|
||||||
obj.Mac = await _cryptoFunctionService.HmacAsync(macData, obj.Key.MacKey, CryptoHashAlgorithm.Sha256);
|
if (obj.Key.MacKey != null)
|
||||||
|
{
|
||||||
|
var macData = new byte[obj.Iv.Length + obj.Data.Length];
|
||||||
|
Buffer.BlockCopy(obj.Iv, 0, macData, 0, obj.Iv.Length);
|
||||||
|
Buffer.BlockCopy(obj.Data, 0, macData, obj.Iv.Length, obj.Data.Length);
|
||||||
|
obj.Mac = await _cryptoFunctionService.HmacAsync(macData, obj.Key.MacKey, CryptoHashAlgorithm.Sha256);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: make this case live when we switch to GCM encryption
|
||||||
|
obj.Type = EncryptionType.AesGcm256_B64;
|
||||||
|
obj.Iv = await _cryptoFunctionService.RandomBytesAsync(12);
|
||||||
|
obj.Data = await _cryptoFunctionService.AesEncryptAsync(data, obj.Iv, obj.Key.EncKey, AesMode.GCM);
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@@ -608,12 +627,15 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
var keyForEnc = await GetKeyForEncryptionAsync(key);
|
var keyForEnc = await GetKeyForEncryptionAsync(key);
|
||||||
var theKey = ResolveLegacyKey(encType, keyForEnc);
|
var theKey = ResolveLegacyKey(encType, keyForEnc);
|
||||||
if (theKey.MacKey != null && mac == null)
|
|
||||||
|
var macType = encType == EncryptionType.AesCbc128_HmacSha256_B64 ||
|
||||||
|
encType == EncryptionType.AesCbc256_HmacSha256_B64;
|
||||||
|
if (macType && theKey.MacKey != null && mac == null)
|
||||||
{
|
{
|
||||||
// Mac required.
|
// Mac required.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (theKey.EncType != encType)
|
if (!theKey.EncTypes.Contains(encType))
|
||||||
{
|
{
|
||||||
// encType unavailable.
|
// encType unavailable.
|
||||||
return null;
|
return null;
|
||||||
@@ -652,7 +674,8 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var decBytes = await _cryptoFunctionService.AesDecryptAsync(dataBytes, ivBytes, encKey);
|
var decBytes = await _cryptoFunctionService.AesDecryptAsync(dataBytes, ivBytes, encKey,
|
||||||
|
encType == EncryptionType.AesGcm256_B64 ? AesMode.GCM : AesMode.CBC);
|
||||||
return Encoding.UTF8.GetString(decBytes);
|
return Encoding.UTF8.GetString(decBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,12 +685,15 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
var keyForEnc = await GetKeyForEncryptionAsync(key);
|
var keyForEnc = await GetKeyForEncryptionAsync(key);
|
||||||
var theKey = ResolveLegacyKey(encType, keyForEnc);
|
var theKey = ResolveLegacyKey(encType, keyForEnc);
|
||||||
if (theKey.MacKey != null && mac == null)
|
|
||||||
|
var macType = encType == EncryptionType.AesCbc128_HmacSha256_B64 ||
|
||||||
|
encType == EncryptionType.AesCbc256_HmacSha256_B64;
|
||||||
|
if (macType && theKey.MacKey != null && mac == null)
|
||||||
{
|
{
|
||||||
// Mac required.
|
// Mac required.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (theKey.EncType != encType)
|
if (!theKey.EncTypes.Contains(encType))
|
||||||
{
|
{
|
||||||
// encType unavailable.
|
// encType unavailable.
|
||||||
return null;
|
return null;
|
||||||
@@ -694,7 +720,8 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await _cryptoFunctionService.AesDecryptAsync(data, iv, theKey.EncKey);
|
return await _cryptoFunctionService.AesDecryptAsync(data, iv, theKey.EncKey,
|
||||||
|
encType == EncryptionType.AesGcm256_B64 ? AesMode.GCM : AesMode.CBC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<byte[]> RsaDecryptAsync(string encValue)
|
private async Task<byte[]> RsaDecryptAsync(string encValue)
|
||||||
@@ -763,7 +790,8 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
private SymmetricCryptoKey ResolveLegacyKey(EncryptionType encKey, SymmetricCryptoKey key)
|
private SymmetricCryptoKey ResolveLegacyKey(EncryptionType encKey, SymmetricCryptoKey key)
|
||||||
{
|
{
|
||||||
if (encKey == EncryptionType.AesCbc128_HmacSha256_B64 && key.EncType == EncryptionType.AesCbc256_B64)
|
if (encKey == EncryptionType.AesCbc128_HmacSha256_B64 &&
|
||||||
|
key.EncTypes.Contains(EncryptionType.AesCbc256_B64))
|
||||||
{
|
{
|
||||||
// Old encrypt-then-mac scheme, make a new key
|
// Old encrypt-then-mac scheme, make a new key
|
||||||
if (_legacyEtmKey == null)
|
if (_legacyEtmKey == null)
|
||||||
@@ -831,6 +859,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
private class EncryptedObject
|
private class EncryptedObject
|
||||||
{
|
{
|
||||||
|
public EncryptionType Type { get; set; }
|
||||||
public byte[] Iv { get; set; }
|
public byte[] Iv { get; set; }
|
||||||
public byte[] Data { get; set; }
|
public byte[] Data { get; set; }
|
||||||
public byte[] Mac { get; set; }
|
public byte[] Mac { get; set; }
|
||||||
|
|||||||
@@ -143,16 +143,24 @@ namespace Bit.Core.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> AesEncryptAsync(byte[] data, byte[] iv, byte[] key)
|
public Task<byte[]> AesEncryptAsync(byte[] data, byte[] iv, byte[] key, AesMode mode)
|
||||||
{
|
{
|
||||||
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
if (mode == AesMode.GCM)
|
||||||
|
{
|
||||||
|
return Task.FromResult(_cryptoPrimitiveService.AesGcmEncrypt(data, iv, key));
|
||||||
|
}
|
||||||
|
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(AesModeToSymmetricAlgorithm(mode));
|
||||||
var cryptoKey = provider.CreateSymmetricKey(key);
|
var cryptoKey = provider.CreateSymmetricKey(key);
|
||||||
return Task.FromResult(CryptographicEngine.Encrypt(cryptoKey, data, iv));
|
return Task.FromResult(CryptographicEngine.Encrypt(cryptoKey, data, iv));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> AesDecryptAsync(byte[] data, byte[] iv, byte[] key)
|
public Task<byte[]> AesDecryptAsync(byte[] data, byte[] iv, byte[] key, AesMode mode)
|
||||||
{
|
{
|
||||||
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
if (mode == AesMode.GCM)
|
||||||
|
{
|
||||||
|
return Task.FromResult(_cryptoPrimitiveService.AesGcmDecrypt(data, iv, key));
|
||||||
|
}
|
||||||
|
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(AesModeToSymmetricAlgorithm(mode));
|
||||||
var cryptoKey = provider.CreateSymmetricKey(key);
|
var cryptoKey = provider.CreateSymmetricKey(key);
|
||||||
return Task.FromResult(CryptographicEngine.Decrypt(cryptoKey, data, iv));
|
return Task.FromResult(CryptographicEngine.Decrypt(cryptoKey, data, iv));
|
||||||
}
|
}
|
||||||
@@ -286,5 +294,18 @@ namespace Bit.Core.Services
|
|||||||
throw new ArgumentException($"Invalid hkdf algorithm type, {hkdfAlgorithm}");
|
throw new ArgumentException($"Invalid hkdf algorithm type, {hkdfAlgorithm}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SymmetricAlgorithm AesModeToSymmetricAlgorithm(AesMode aesMode)
|
||||||
|
{
|
||||||
|
switch (aesMode)
|
||||||
|
{
|
||||||
|
case AesMode.CBC:
|
||||||
|
return SymmetricAlgorithm.AesCbcPkcs7;
|
||||||
|
case AesMode.GCM:
|
||||||
|
return SymmetricAlgorithm.AesGcm;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Invalid aes mode type, {aesMode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,17 @@ namespace Bit.iOS.Core.Services
|
|||||||
return keyBytes;
|
return keyBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] AesGcmEncrypt(byte[] data, byte[] iv, byte[] key)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] AesGcmDecrypt(byte[] data, byte[] iv, byte[] key)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
// ref: http://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/CommonCrypto/CommonKeyDerivation.h
|
// ref: http://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/CommonCrypto/CommonKeyDerivation.h
|
||||||
[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
|
[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
|
||||||
private extern static int CCKeyCerivationPBKDF(uint algorithm, IntPtr password, nuint passwordLen,
|
private extern static int CCKeyCerivationPBKDF(uint algorithm, IntPtr password, nuint passwordLen,
|
||||||
|
|||||||
@@ -144,13 +144,27 @@
|
|||||||
<ImageAsset Include="Resources\Assets.xcassets\AppIcons.appiconset\Contents.json">
|
<ImageAsset Include="Resources\Assets.xcassets\AppIcons.appiconset\Contents.json">
|
||||||
<Visible>false</Visible>
|
<Visible>false</Visible>
|
||||||
</ImageAsset>
|
</ImageAsset>
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\Contents.json" />
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\Contents.json">
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo.png" />
|
<Visible>false</Visible>
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo%402x.png" />
|
</ImageAsset>
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo%403x.png" />
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo.png">
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white.png" />
|
<Visible>false</Visible>
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white%402x.png" />
|
</ImageAsset>
|
||||||
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white%403x.png" />
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo%402x.png">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</ImageAsset>
|
||||||
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo%403x.png">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</ImageAsset>
|
||||||
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white.png">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</ImageAsset>
|
||||||
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white%402x.png">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</ImageAsset>
|
||||||
|
<ImageAsset Include="Resources\Assets.xcassets\LaunchScreen.imageset\logo_white%403x.png">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
</ImageAsset>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InterfaceDefinition Include="LaunchScreen.storyboard" />
|
<InterfaceDefinition Include="LaunchScreen.storyboard" />
|
||||||
|
|||||||
Reference in New Issue
Block a user