mirror of
https://github.com/bitwarden/mobile
synced 2026-01-19 17:03:21 +00:00
refactor for enc type header and cryptokey
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
using XLabs.Ioc;
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
@@ -15,10 +16,58 @@ namespace Bit.App.Models
|
||||
throw new ArgumentException(nameof(encryptedString));
|
||||
}
|
||||
|
||||
var headerPieces = encryptedString.Split('.');
|
||||
string[] encPieces;
|
||||
if(headerPieces.Length == 2 && Enum.TryParse(headerPieces[0], out EncryptionType encType))
|
||||
{
|
||||
EncryptionType = encType;
|
||||
encPieces = headerPieces[1].Split('|');
|
||||
}
|
||||
else if(headerPieces.Length == 1)
|
||||
{
|
||||
encPieces = headerPieces[0].Split('|');
|
||||
EncryptionType = encPieces.Length == 3 ? EncryptionType.AesCbc128_HmacSha256_B64 : EncryptionType.AesCbc256_B64;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Malformed header.");
|
||||
}
|
||||
|
||||
switch(EncryptionType)
|
||||
{
|
||||
case EncryptionType.AesCbc256_B64:
|
||||
if(encPieces.Length != 2)
|
||||
{
|
||||
throw new ArgumentException("Malformed encPieces.");
|
||||
}
|
||||
InitializationVector = encPieces[0];
|
||||
CipherText = encPieces[1];
|
||||
break;
|
||||
case EncryptionType.AesCbc128_HmacSha256_B64:
|
||||
case EncryptionType.AesCbc256_HmacSha256_B64:
|
||||
if(encPieces.Length != 3)
|
||||
{
|
||||
throw new ArgumentException("Malformed encPieces.");
|
||||
}
|
||||
InitializationVector = encPieces[0];
|
||||
CipherText = encPieces[1];
|
||||
Mac = encPieces[2];
|
||||
break;
|
||||
case EncryptionType.RsaOaep_Sha256_B64:
|
||||
if(encPieces.Length != 1)
|
||||
{
|
||||
throw new ArgumentException("Malformed encPieces.");
|
||||
}
|
||||
CipherText = encPieces[0];
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unknown encType.");
|
||||
}
|
||||
|
||||
EncryptedString = encryptedString;
|
||||
}
|
||||
|
||||
public CipherString(string initializationVector, string cipherText, string mac = null)
|
||||
public CipherString(EncryptionType encryptionType, string initializationVector, string cipherText, string mac = null)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(initializationVector))
|
||||
{
|
||||
@@ -30,30 +79,24 @@ namespace Bit.App.Models
|
||||
throw new ArgumentNullException(nameof(cipherText));
|
||||
}
|
||||
|
||||
EncryptedString = string.Format("{0}|{1}", initializationVector, cipherText);
|
||||
EncryptionType = encryptionType;
|
||||
EncryptedString = string.Format("{0}.{1}|{2}", (byte)encryptionType, initializationVector, cipherText);
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(mac))
|
||||
{
|
||||
EncryptedString = string.Format("{0}|{1}", EncryptedString, mac);
|
||||
}
|
||||
|
||||
CipherText = cipherText;
|
||||
InitializationVector = initializationVector;
|
||||
Mac = mac;
|
||||
}
|
||||
|
||||
public EncryptionType EncryptionType { get; private set; }
|
||||
public string EncryptedString { get; private set; }
|
||||
public string InitializationVector => EncryptedString?.Split('|')[0] ?? null;
|
||||
public string CipherText => EncryptedString?.Split('|')[1] ?? null;
|
||||
public string Mac
|
||||
{
|
||||
get
|
||||
{
|
||||
var pieces = EncryptedString?.Split('|') ?? new string[0];
|
||||
if(pieces.Length > 2)
|
||||
{
|
||||
return pieces[2];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public string InitializationVector { get; private set; }
|
||||
public string CipherText { get; private set; }
|
||||
public string Mac { get; private set; }
|
||||
public byte[] InitializationVectorBytes => Convert.FromBase64String(InitializationVector);
|
||||
public byte[] CipherTextBytes => Convert.FromBase64String(CipherText);
|
||||
public byte[] MacBytes => Mac == null ? null : Convert.FromBase64String(Mac);
|
||||
|
||||
62
src/App/Models/CryptoKey.cs
Normal file
62
src/App/Models/CryptoKey.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Bit.App.Enums;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class CryptoKey
|
||||
{
|
||||
public CryptoKey(byte[] rawBytes, EncryptionType? encType = null)
|
||||
{
|
||||
if(rawBytes == null || rawBytes.Length == 0)
|
||||
{
|
||||
throw new Exception("Must provide keyBytes.");
|
||||
}
|
||||
|
||||
if(encType == null)
|
||||
{
|
||||
if(rawBytes.Length == 32)
|
||||
{
|
||||
encType = EncryptionType.AesCbc256_B64;
|
||||
}
|
||||
else if(rawBytes.Length == 64)
|
||||
{
|
||||
encType = EncryptionType.AesCbc256_HmacSha256_B64;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unable to determine encType.");
|
||||
}
|
||||
}
|
||||
|
||||
EncryptionType = encType.Value;
|
||||
Key = rawBytes;
|
||||
|
||||
if(EncryptionType == EncryptionType.AesCbc256_B64 && Key.Length == 32)
|
||||
{
|
||||
EncKey = Key;
|
||||
MacKey = null;
|
||||
}
|
||||
else if(EncryptionType == EncryptionType.AesCbc128_HmacSha256_B64 && Key.Length == 32)
|
||||
{
|
||||
EncKey = Key.Take(16).ToArray();
|
||||
MacKey = Key.Skip(16).Take(16).ToArray();
|
||||
}
|
||||
else if(EncryptionType == EncryptionType.AesCbc256_HmacSha256_B64 && Key.Length == 64)
|
||||
{
|
||||
EncKey = Key.Take(32).ToArray();
|
||||
MacKey = Key.Skip(32).Take(32).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsupported encType/key length.");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Key { get; set; }
|
||||
public string B64Key => Convert.ToBase64String(Key);
|
||||
public byte[] EncKey { get; set; }
|
||||
public byte[] MacKey { get; set; }
|
||||
public EncryptionType EncryptionType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
public class FullLoginResult : LoginResult
|
||||
{
|
||||
public bool TwoFactorRequired { get; set; }
|
||||
public byte[] Key { get; set; }
|
||||
public CryptoKey Key { get; set; }
|
||||
public string MasterPasswordHash { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user