経緯
.NET Cloud Client Libraries を使用して、GCEインスタンス(Windows)を作成する機会があったのですがパスワードの復号化に苦戦しましたので
復号化手順を共有します。
手順
公開鍵・秘密鍵を生成します。KeyPairGeneratorはjavaのクラスです。
C#から利用するために、IKVMと呼ばれるライブラリを使用します。
private KeyPair generateKeys()
{
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
// Key moduli for encryption/decryption are 2048 bits long.
keyGen.initialize(2048);
return keyGen.genKeyPair();
}
GCEインスタンスにメタデータを設定します。
// Generate the public/private key pair for encryption and decryption.
KeyPair keys = generateKeys();
JObject buildedKeys = BuildKeyMetadata(keys);
//Replace Metadata
string newItemString = buildedKeys.ToString().Replace("\r\n", "");
// Get the list containing all of the Metadata entries for this instance.
IList<Metadata.ItemsData> items = oldMetaData.Items;
// If the instance has no metadata, items can be returned as null.
if (items == null)
{
items = new List<Metadata.ItemsData>();
oldMetaData.Items = items;
}
// Find the "windows-keys" entry and update it.
bool isFound = false;
foreach (Metadata.ItemsData item in items)
{
if (item.Key == "windows-keys")
{
// Replace item's value with the new entry.
// To prevent race conditions, production code may want to maintain a
// list where the oldest entries are removed once the 32KB limit is
// reached for the metadata entry.
item.Value = newItemString;
isFound = true;
break;
}
}
if (!isFound)
{
// "windows.keys" entry doesn't exist in the metadata - append it.
// This occurs when running password-reset for the first time on an instance.
Metadata.ItemsData addItem = new Metadata.ItemsData
{
Key = "windows-keys",
Value = newItemString
};
items.Add(addItem);
}
oldMetaData.Items = items;
//Set Metadata
InstancesResource.SetMetadataRequest setMetadataReq = new InstancesResource.SetMetadataRequest(_Client, oldMetaData, projectId,
RegionId, ServerId);
await setMetadataReq.ExecuteAsync(_CancellationToken);
インスタンスから出力されたシリアルポートから暗号化されたパスワードを取得します。
//GetPassword
string entries;
while (true)
{
InstancesResource.GetSerialPortOutputRequest getSerialPortOutputReq =
new InstancesResource.GetSerialPortOutputRequest(_Client, _Profile.ProjectId, _Task.RegionId,
_Task.ServerId)
{
Port = 4
};
SerialPortOutput getSerialPortOutputRes = await getSerialPortOutputReq.ExecuteAsync(_CancellationToken);
entries = getSerialPortOutputRes.Contents;
if (entries != "")
{
break;
}
await Task.Delay(10000, _CancellationToken);
}
string[] array = entries.Split('}');
string encrypto;
if (array.Length > 1)
{
encrypto = array[array.Length - 2] + "}";
}
else
{
encrypto = array[0] + "}";
}
JObject passwordDict = JObject.Parse(encrypto);
string encryptedPassword = ((JValue)passwordDict["encryptedPassword"]).ToString(CultureInfo.CurrentCulture);
パスワードの復号化をします。
byte[] plainTextBytes = Convert.FromBase64String(encryptedPassword);
Cipher decryptionCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
OAEPParameterSpec oaepParameterSpec =
new OAEPParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
decryptionCipher.init(Cipher.DECRYPT_MODE, keys.getPrivate(), oaepParameterSpec);
byte[] decryptedText = decryptionCipher.doFinal(plainTextBytes);
string answer = Encoding.UTF8.GetString(decryptedText);
↧