Los ejemplos de C# de esta sección implementan una aplicación de ejemplo que muestra cómo crear las firmas para distribuciones privadas de CloudFront mediante instrucciones de políticas predefinidas y personalizadas. Los ejemplos incluyen funciones de utilidad basadas en el AWS SDK para .NET
También puede crear URL firmadas y cookies firmadas mediante SDK para .NET. En la Referencia de la API SDK para .NET, consulte los siguientes temas:
-
URL firmadas: AmazonCloudFrontUrlSigner
-
Cookies firmadas: AmazonCloudFrontCookieSigner
Para descargar el código, diríjase a Código de firma en C#.
nota
Crear una firma de URL es solo una parte del proceso de entrega de contenido privado mediante una URL firmada. Para obtener más información, consulte Uso de URL firmadas. Para obtener más información sobre el uso de cookies firmadas, consulte Uso de cookies firmadas.
Uso de una clave RSA en .NET Framework
Para utilizar una clave RSA en .NET Framework, debe convertir el archivo.pem suministrado por AWS al formato XML que utiliza el .NET Framework.
Después de la conversión, el archivo de clave privada RSA estará en el siguiente formato:
ejemplo Clave privada RSA en formato XML de .NET Framework
<RSAKeyValue>
<Modulus>
wO5IvYCP5UcoCKDo1dcspoMehWBZcyfs9QEzGi6Oe5y+ewGr1oW+vB2GPB
ANBiVPcUHTFWhwaIBd3oglmF0lGQljP/jOfmXHUK2kUUnLnJp+oOBL2NiuFtqcW6h/L5lIpD8Yq+NRHg
Ty4zDsyr2880MvXv88yEFURCkqEXAMPLE=
</Modulus>
<Exponent>AQAB</Exponent>
<P>
5bmKDaTz
npENGVqz4Cea8XPH+sxt+2VaAwYnsarVUoSBeVt8WLloVuZGG9IZYmH5KteXEu7fZveYd9UEXAMPLE==
</P>
<Q>
1v9l/WN1a1N3rOK4VGoCokx7kR2SyTMSbZgF9IWJNOugR/WZw7HTnjipO3c9dy1Ms9pUKwUF4
6d7049EXAMPLE==
</Q>
<DP>
RgrSKuLWXMyBH+/l1Dx/I4tXuAJIrlPyo+VmiOc7b5NzHptkSHEPfR9s1
OK0VqjknclqCJ3Ig86OMEtEXAMPLE==
</DP>
<DQ>
pjPjvSFw+RoaTu0pgCA/jwW/FGyfN6iim1RFbkT4
z49DZb2IM885f3vf35eLTaEYRYUHQgZtChNEV0TEXAMPLE==
</DQ>
<InverseQ>
nkvOJTg5QtGNgWb9i
cVtzrL/1pFEOHbJXwEJdU99N+7sMK+1066DL/HSBUCD63qD4USpnf0myc24in0EXAMPLE==</InverseQ>
<D>
Bc7mp7XYHynuPZxChjWNJZIq+A73gm0ASDv6At7F8Vi9r0xUlQe/v0AQS3ycN8QlyR4XMbzMLYk
3yjxFDXo4ZKQtOGzLGteCU2srANiLv26/imXA8FVidZftTAtLviWQZBVPTeYIA69ATUYPEq0a5u5wjGy
UOij9OWyuEXAMPLE=
</D>
</RSAKeyValue>
Método de firma de políticas predefinidas en C#
El siguiente código C# crea una URL firmada que utiliza una política predefinida siguiendo los pasos que se indican a continuación:
-
Crea una instrucción de política.
-
La instrucción de política aplica la función hash mediante SHA1 y firma el resultado con RSA y la clave privada cuya clave pública correspondiente se encuentra en un grupo de claves de confianza.
-
Codifica con base64 la instrucción de política a la que se le ha aplicado una función hash y firmada y sustituye caracteres especiales para que la cadena se pueda usar tranquilamente como parámetro de solicitud de URL.
-
Encadena los valores.
Para ver la implementación completa, consulte el ejemplo disponible en Código de firma en C#.
nota
Se devuelve keyId
al cargar una clave pública a CloudFront. Para obtener más información, consulte
&Key-Pair-Id.
ejemplo : método de firma de políticas predefinidas en C#
public static string ToUrlSafeBase64String(byte[] bytes)
{
return System.Convert.ToBase64String(bytes)
.Replace('+', '-')
.Replace('=', '_')
.Replace('/', '~');
}
public static string CreateCannedPrivateURL(string urlString,
string durationUnits, string durationNumber, string pathToPolicyStmnt,
string pathToPrivateKey, string keyId)
{
// args[] 0-thisMethod, 1-resourceUrl, 2-seconds-minutes-hours-days
// to expiration, 3-numberOfPreviousUnits, 4-pathToPolicyStmnt,
// 5-pathToPrivateKey, 6-keyId
TimeSpan timeSpanInterval = GetDuration(durationUnits, durationNumber);
// Create the policy statement.
string strPolicy = CreatePolicyStatement(pathToPolicyStmnt,
urlString,
DateTime.Now,
DateTime.Now.Add(timeSpanInterval),
"0.0.0.0/0");
if ("Error!" == strPolicy) return "Invalid time frame." +
"Start time cannot be greater than end time.";
// Copy the expiration time defined by policy statement.
string strExpiration = CopyExpirationTimeFromPolicy(strPolicy);
// Read the policy into a byte buffer.
byte[] bufferPolicy = Encoding.ASCII.GetBytes(strPolicy);
// Initialize the SHA1CryptoServiceProvider object and hash the policy data.
using (SHA1CryptoServiceProvider
cryptoSHA1 = new SHA1CryptoServiceProvider())
{
bufferPolicy = cryptoSHA1.ComputeHash(bufferPolicy);
// Initialize the RSACryptoServiceProvider object.
RSACryptoServiceProvider providerRSA = new RSACryptoServiceProvider();
XmlDocument xmlPrivateKey = new XmlDocument();
// Load your private key, which you created by converting your
// .pem file to the XML format that the .NET framework uses.
// Several tools are available.
xmlPrivateKey.Load(pathToPrivateKey);
// Format the RSACryptoServiceProvider providerRSA and
// create the signature.
providerRSA.FromXmlString(xmlPrivateKey.InnerXml);
RSAPKCS1SignatureFormatter rsaFormatter =
new RSAPKCS1SignatureFormatter(providerRSA);
rsaFormatter.SetHashAlgorithm("SHA1");
byte[] signedPolicyHash = rsaFormatter.CreateSignature(bufferPolicy);
// Convert the signed policy to URL-safe base64 encoding and
// replace unsafe characters + = / with the safe characters - _ ~
string strSignedPolicy = ToUrlSafeBase64String(signedPolicyHash);
// Concatenate the URL, the timestamp, the signature,
// and the key pair ID to form the signed URL.
return urlString +
"?Expires=" +
strExpiration +
"&Signature=" +
strSignedPolicy +
"&Key-Pair-Id=" +
keyId;
}
}
Método de firma de políticas personalizadas en C#
El siguiente código C# crea una URL firmada que utiliza una política personalizada siguiendo los pasos que se indican a continuación:
-
Crea una instrucción de política.
-
Codifica con base64 la instrucción de política y sustituye caracteres especiales para que la cadena se pueda usar tranquilamente como parámetro de solicitud de URL.
-
La instrucción de política aplica la función hash mediante SHA1 y cifra el resultado mediante RSA y la clave privada cuya clave pública correspondiente se encuentra en un grupo de claves de confianza.
-
Codifica con base64 la instrucción de política a la que se le ha aplicado una función hash y sustituye caracteres especiales para que la cadena se pueda usar tranquilamente como parámetro de solicitud de URL.
-
Encadena los valores.
Para ver la implementación completa, consulte el ejemplo disponible en Código de firma en C#.
nota
Se devuelve keyId
al cargar una clave pública a CloudFront. Para obtener más información, consulte
&Key-Pair-Id.
ejemplo : método de firma de políticas personalizadas en C#
public static string ToUrlSafeBase64String(byte[] bytes)
{
return System.Convert.ToBase64String(bytes)
.Replace('+', '-')
.Replace('=', '_')
.Replace('/', '~');
}
public static string CreateCustomPrivateURL(string urlString,
string durationUnits, string durationNumber, string startIntervalFromNow,
string ipaddress, string pathToPolicyStmnt, string pathToPrivateKey,
string keyId)
{
// args[] 0-thisMethod, 1-resourceUrl, 2-seconds-minutes-hours-days
// to expiration, 3-numberOfPreviousUnits, 4-starttimeFromNow,
// 5-ip_address, 6-pathToPolicyStmt, 7-pathToPrivateKey, 8-keyId
TimeSpan timeSpanInterval = GetDuration(durationUnits, durationNumber);
TimeSpan timeSpanToStart = GetDurationByUnits(durationUnits,
startIntervalFromNow);
if (null == timeSpanToStart)
return "Invalid duration units." +
"Valid options: seconds, minutes, hours, or days";
string strPolicy = CreatePolicyStatement(
pathToPolicyStmnt, urlString, DateTime.Now.Add(timeSpanToStart),
DateTime.Now.Add(timeSpanInterval), ipaddress);
// Read the policy into a byte buffer.
byte[] bufferPolicy = Encoding.ASCII.GetBytes(strPolicy);
// Convert the policy statement to URL-safe base64 encoding and
// replace unsafe characters + = / with the safe characters - _ ~
string urlSafePolicy = ToUrlSafeBase64String(bufferPolicy);
// Initialize the SHA1CryptoServiceProvider object and hash the policy data.
byte[] bufferPolicyHash;
using (SHA1CryptoServiceProvider cryptoSHA1 =
new SHA1CryptoServiceProvider())
{
bufferPolicyHash = cryptoSHA1.ComputeHash(bufferPolicy);
// Initialize the RSACryptoServiceProvider object.
RSACryptoServiceProvider providerRSA = new RSACryptoServiceProvider();
XmlDocument xmlPrivateKey = new XmlDocument();
// Load your private key, which you created by converting your
// .pem file to the XML format that the .NET framework uses.
// Several tools are available.
xmlPrivateKey.Load(pathToPrivateKey);
// Format the RSACryptoServiceProvider providerRSA
// and create the signature.
providerRSA.FromXmlString(xmlPrivateKey.InnerXml);
RSAPKCS1SignatureFormatter RSAFormatter =
new RSAPKCS1SignatureFormatter(providerRSA);
RSAFormatter.SetHashAlgorithm("SHA1");
byte[] signedHash = RSAFormatter.CreateSignature(bufferPolicyHash);
// Convert the signed policy to URL-safe base64 encoding and
// replace unsafe characters + = / with the safe characters - _ ~
string strSignedPolicy = ToUrlSafeBase64String(signedHash);
return urlString +
"?Policy=" +
urlSafePolicy +
"&Signature=" +
strSignedPolicy +
"&Key-Pair-Id=" +
keyId;
}
}
Métodos de utilidades para generar firmas
Los siguientes métodos obtienen la instrucción de política de un archivo y analizan intervalos de tiempo para generar firmas.
ejemplo : métodos de utilidades para generar firmas
public static string CreatePolicyStatement(string policyStmnt,
string resourceUrl,
DateTime startTime,
DateTime endTime,
string ipAddress)
{
// Create the policy statement.
FileStream streamPolicy = new FileStream(policyStmnt, FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(streamPolicy))
{
string strPolicy = reader.ReadToEnd();
TimeSpan startTimeSpanFromNow = (startTime - DateTime.Now);
TimeSpan endTimeSpanFromNow = (endTime - DateTime.Now);
TimeSpan intervalStart =
(DateTime.UtcNow.Add(startTimeSpanFromNow)) -
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan intervalEnd =
(DateTime.UtcNow.Add(endTimeSpanFromNow)) -
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
int startTimestamp = (int)intervalStart.TotalSeconds; // START_TIME
int endTimestamp = (int)intervalEnd.TotalSeconds; // END_TIME
if (startTimestamp > endTimestamp)
return "Error!";
// Replace variables in the policy statement.
strPolicy = strPolicy.Replace("RESOURCE", resourceUrl);
strPolicy = strPolicy.Replace("START_TIME", startTimestamp.ToString());
strPolicy = strPolicy.Replace("END_TIME", endTimestamp.ToString());
strPolicy = strPolicy.Replace("IP_ADDRESS", ipAddress);
strPolicy = strPolicy.Replace("EXPIRES", endTimestamp.ToString());
return strPolicy;
}
}
public static TimeSpan GetDuration(string units, string numUnits)
{
TimeSpan timeSpanInterval = new TimeSpan();
switch (units)
{
case "seconds":
timeSpanInterval = new TimeSpan(0, 0, 0, int.Parse(numUnits));
break;
case "minutes":
timeSpanInterval = new TimeSpan(0, 0, int.Parse(numUnits), 0);
break;
case "hours":
timeSpanInterval = new TimeSpan(0, int.Parse(numUnits), 0 ,0);
break;
case "days":
timeSpanInterval = new TimeSpan(int.Parse(numUnits),0 ,0 ,0);
break;
default:
Console.WriteLine("Invalid time units;" +
"use seconds, minutes, hours, or days");
break;
}
return timeSpanInterval;
}
private static TimeSpan GetDurationByUnits(string durationUnits,
string startIntervalFromNow)
{
switch (durationUnits)
{
case "seconds":
return new TimeSpan(0, 0, int.Parse(startIntervalFromNow));
case "minutes":
return new TimeSpan(0, int.Parse(startIntervalFromNow), 0);
case "hours":
return new TimeSpan(int.Parse(startIntervalFromNow), 0, 0);
case "days":
return new TimeSpan(int.Parse(startIntervalFromNow), 0, 0, 0);
default:
return new TimeSpan(0, 0, 0, 0);
}
}
public static string CopyExpirationTimeFromPolicy(string policyStatement)
{
int startExpiration = policyStatement.IndexOf("EpochTime");
string strExpirationRough = policyStatement.Substring(startExpiration +
"EpochTime".Length);
char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
List<char> listDigits = new List<char>(digits);
StringBuilder buildExpiration = new StringBuilder(20);
foreach (char c in strExpirationRough)
{
if (listDigits.Contains(c))
buildExpiration.Append(c);
}
return buildExpiration.ToString();
}
Véase también