2
2
using System . Collections ;
3
3
using System . Diagnostics ;
4
4
using System . IO ;
5
+ using crypto . openpgp ;
5
6
using Org . BouncyCastle . Asn1 ;
6
7
using Org . BouncyCastle . Asn1 . Misc ;
7
8
using Org . BouncyCastle . Asn1 . X9 ;
@@ -1116,60 +1117,6 @@ public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[]
1116
1117
return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , pubKey ) ;
1117
1118
}
1118
1119
1119
- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
1120
- {
1121
- SXprUtilities reader = new SXprUtilities ( inputStream ) ;
1122
-
1123
- reader . SkipOpenParenthesis ( ) ;
1124
-
1125
- string type = reader . ReadString ( ) ;
1126
- if ( type . Equals ( "protected-private-key" ) )
1127
- {
1128
- reader . SkipOpenParenthesis ( ) ;
1129
-
1130
- string curveName ;
1131
-
1132
- string keyType = reader . ReadString ( ) ;
1133
- if ( keyType . Equals ( "ecc" ) )
1134
- {
1135
- reader . SkipOpenParenthesis ( ) ;
1136
-
1137
- string curveID = reader . ReadString ( ) ;
1138
- curveName = reader . ReadString ( ) ;
1139
-
1140
- reader . SkipCloseParenthesis ( ) ;
1141
- }
1142
- else
1143
- {
1144
- throw new PgpException ( "no curve details found" ) ;
1145
- }
1146
-
1147
- byte [ ] qVal ;
1148
-
1149
- reader . SkipOpenParenthesis ( ) ;
1150
-
1151
- type = reader . ReadString ( ) ;
1152
- if ( type . Equals ( "q" ) )
1153
- {
1154
- qVal = reader . ReadBytes ( ) ;
1155
- }
1156
- else
1157
- {
1158
- throw new PgpException ( "no q value found" ) ;
1159
- }
1160
-
1161
- reader . SkipCloseParenthesis ( ) ;
1162
-
1163
- byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
1164
- // TODO: check SHA-1 hash.
1165
-
1166
- return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1167
- new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
1168
- }
1169
-
1170
- throw new PgpException ( "unknown key type found" ) ;
1171
- }
1172
-
1173
1120
/// <summary>
1174
1121
/// Parse a secret key from one of the GPG S expression keys.
1175
1122
/// </summary>
@@ -1179,7 +1126,7 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[
1179
1126
/// </remarks>
1180
1127
public static PgpSecretKey ParseSecretKeyFromSExpr ( Stream inputStream , char [ ] passPhrase )
1181
1128
{
1182
- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true ) ;
1129
+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , false ) , true , null ) ;
1183
1130
}
1184
1131
1185
1132
/// <summary>
@@ -1190,7 +1137,7 @@ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] pa
1190
1137
/// </remarks>
1191
1138
public static PgpSecretKey ParseSecretKeyFromSExprUtf8 ( Stream inputStream , char [ ] passPhrase )
1192
1139
{
1193
- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true ) ;
1140
+ return DoParseSecretKeyFromSExpr ( inputStream , PgpUtilities . EncodePassPhrase ( passPhrase , true ) , true , null ) ;
1194
1141
}
1195
1142
1196
1143
/// <summary>
@@ -1201,14 +1148,16 @@ public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[
1201
1148
/// </remarks>
1202
1149
public static PgpSecretKey ParseSecretKeyFromSExprRaw ( Stream inputStream , byte [ ] rawPassPhrase )
1203
1150
{
1204
- return DoParseSecretKeyFromSExpr ( new SXprUtilities ( inputStream ) , rawPassPhrase , false ) ;
1151
+ return DoParseSecretKeyFromSExpr ( inputStream , rawPassPhrase , false , null ) ;
1205
1152
}
1206
1153
1207
1154
/// <summary>
1208
1155
/// Parse a secret key from one of the GPG S expression keys.
1209
1156
/// </summary>
1210
- internal static PgpSecretKey DoParseSecretKeyFromSExpr ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase )
1157
+ internal static PgpSecretKey DoParseSecretKeyFromSExpr ( Stream inputStream , byte [ ] rawPassPhrase , bool clearPassPhrase , PgpPublicKey pubKey )
1211
1158
{
1159
+ SXprReader reader = new SXprReader ( inputStream ) ;
1160
+
1212
1161
reader . SkipOpenParenthesis ( ) ;
1213
1162
1214
1163
string type = reader . ReadString ( ) ;
@@ -1272,28 +1221,87 @@ internal static PgpSecretKey DoParseSecretKeyFromSExpr(SXprUtilities reader, byt
1272
1221
throw new PgpException ( "no q value found" ) ;
1273
1222
}
1274
1223
1275
- PublicKeyPacket pubPacket = new PublicKeyPacket (
1276
- flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1277
- new ECDsaPublicBcpgKey ( curveOid , new BigInteger ( 1 , qVal ) ) ) ;
1224
+ if ( pubKey == null )
1225
+ {
1226
+ PublicKeyPacket pubPacket = new PublicKeyPacket (
1227
+ flags == "eddsa" ? PublicKeyAlgorithmTag . EdDsa : PublicKeyAlgorithmTag . ECDsa , DateTime . UtcNow ,
1228
+ new ECDsaPublicBcpgKey ( curveOid , new BigInteger ( 1 , qVal ) ) ) ;
1229
+ pubKey = new PgpPublicKey ( pubPacket ) ;
1230
+ }
1278
1231
1279
1232
reader . SkipCloseParenthesis ( ) ;
1280
1233
1281
- byte [ ] dValue = GetDValue ( reader , rawPassPhrase , clearPassPhrase , curveName ) ;
1282
- // TODO: check SHA-1 hash.
1234
+ byte [ ] dValue = GetDValue ( reader , pubKey . PublicKeyPacket , rawPassPhrase , clearPassPhrase , curveName ) ;
1283
1235
1284
- return new PgpSecretKey ( new SecretKeyPacket ( pubPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1285
- new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , new PgpPublicKey ( pubPacket ) ) ;
1236
+ return new PgpSecretKey ( new SecretKeyPacket ( pubKey . PublicKeyPacket , SymmetricKeyAlgorithmTag . Null , null , null ,
1237
+ new ECSecretBcpgKey ( new BigInteger ( 1 , dValue ) ) . GetEncoded ( ) ) , pubKey ) ;
1286
1238
}
1287
1239
1288
1240
throw new PgpException ( "unknown key type found" ) ;
1289
1241
}
1290
1242
1291
- private static byte [ ] GetDValue ( SXprUtilities reader , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
1243
+ private static void WriteSExprPublicKey ( SXprWriter writer , PublicKeyPacket pubPacket , string curveName , string protectedAt )
1244
+ {
1245
+ writer . StartList ( ) ;
1246
+ switch ( pubPacket . Algorithm )
1247
+ {
1248
+ case PublicKeyAlgorithmTag . ECDsa :
1249
+ case PublicKeyAlgorithmTag . EdDsa :
1250
+ writer . WriteString ( "ecc" ) ;
1251
+ writer . StartList ( ) ;
1252
+ writer . WriteString ( "curve" ) ;
1253
+ writer . WriteString ( curveName ) ;
1254
+ writer . EndList ( ) ;
1255
+ if ( pubPacket . Algorithm == PublicKeyAlgorithmTag . EdDsa )
1256
+ {
1257
+ writer . StartList ( ) ;
1258
+ writer . WriteString ( "flags" ) ;
1259
+ writer . WriteString ( "eddsa" ) ;
1260
+ writer . EndList ( ) ;
1261
+ }
1262
+ writer . StartList ( ) ;
1263
+ writer . WriteString ( "q" ) ;
1264
+ writer . WriteBytes ( ( ( ECDsaPublicBcpgKey ) pubPacket . Key ) . EncodedPoint . ToByteArrayUnsigned ( ) ) ;
1265
+ writer . EndList ( ) ;
1266
+ break ;
1267
+
1268
+ case PublicKeyAlgorithmTag . RsaEncrypt :
1269
+ case PublicKeyAlgorithmTag . RsaSign :
1270
+ case PublicKeyAlgorithmTag . RsaGeneral :
1271
+ RsaPublicBcpgKey rsaK = ( RsaPublicBcpgKey ) pubPacket . Key ;
1272
+ writer . WriteString ( "rsa" ) ;
1273
+ writer . StartList ( ) ;
1274
+ writer . WriteString ( "n" ) ;
1275
+ writer . WriteBytes ( rsaK . Modulus . ToByteArrayUnsigned ( ) ) ;
1276
+ writer . EndList ( ) ;
1277
+ writer . StartList ( ) ;
1278
+ writer . WriteString ( "e" ) ;
1279
+ writer . WriteBytes ( rsaK . PublicExponent . ToByteArrayUnsigned ( ) ) ;
1280
+ writer . EndList ( ) ;
1281
+ break ;
1282
+
1283
+ // TODO: DSA, etc.
1284
+ default :
1285
+ throw new PgpException ( "unsupported algorithm in S expression" ) ;
1286
+ }
1287
+
1288
+ if ( protectedAt != null )
1289
+ {
1290
+ writer . StartList ( ) ;
1291
+ writer . WriteString ( "protected-at" ) ;
1292
+ writer . WriteString ( protectedAt ) ;
1293
+ writer . EndList ( ) ;
1294
+ }
1295
+ writer . EndList ( ) ;
1296
+ }
1297
+
1298
+ private static byte [ ] GetDValue ( SXprReader reader , PublicKeyPacket publicKey , byte [ ] rawPassPhrase , bool clearPassPhrase , string curveName )
1292
1299
{
1293
1300
string type ;
1294
1301
reader . SkipOpenParenthesis ( ) ;
1295
1302
1296
1303
string protection ;
1304
+ string protectedAt = null ;
1297
1305
S2k s2k ;
1298
1306
byte [ ] iv ;
1299
1307
byte [ ] secKeyData ;
@@ -1312,26 +1320,42 @@ private static byte[] GetDValue(SXprUtilities reader, byte[] rawPassPhrase, bool
1312
1320
reader . SkipCloseParenthesis ( ) ;
1313
1321
1314
1322
secKeyData = reader . ReadBytes ( ) ;
1323
+
1324
+ reader . SkipCloseParenthesis ( ) ;
1325
+
1326
+ reader . SkipOpenParenthesis ( ) ;
1327
+
1328
+ if ( reader . ReadString ( ) . Equals ( "protected-at" ) )
1329
+ {
1330
+ protectedAt = reader . ReadString ( ) ;
1331
+ }
1315
1332
}
1316
1333
else
1317
1334
{
1318
1335
throw new PgpException ( "protected block not found" ) ;
1319
1336
}
1320
1337
1321
- // Valid values of protection: openpgp-s2k3-sha1-aes-cbc, openpgp-s2k3-ocb-aes, openpgp-native
1322
1338
byte [ ] data ;
1323
1339
KeyParameter key ;
1324
1340
1325
1341
switch ( protection )
1326
1342
{
1343
+ case "openpgp-s2k3-sha1-aes256-cbc" :
1327
1344
case "openpgp-s2k3-sha1-aes-cbc" :
1328
- key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1329
- data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1345
+ SymmetricKeyAlgorithmTag symmAlg =
1346
+ protection . Equals ( "openpgp-s2k3-sha1-aes256-cbc" ) ? SymmetricKeyAlgorithmTag . Aes256 : SymmetricKeyAlgorithmTag . Aes128 ;
1347
+ key = PgpUtilities . DoMakeKeyFromPassPhrase ( symmAlg , s2k , rawPassPhrase , clearPassPhrase ) ;
1348
+ data = RecoverKeyData ( symmAlg , "/CBC/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1349
+ // TODO: check SHA-1 hash.
1330
1350
break ;
1331
1351
1332
1352
case "openpgp-s2k3-ocb-aes" :
1353
+ MemoryStream aad = new MemoryStream ( ) ;
1354
+ WriteSExprPublicKey ( new SXprWriter ( aad ) , publicKey , curveName , protectedAt ) ;
1333
1355
key = PgpUtilities . DoMakeKeyFromPassPhrase ( SymmetricKeyAlgorithmTag . Aes128 , s2k , rawPassPhrase , clearPassPhrase ) ;
1334
- data = RecoverKeyData ( SymmetricKeyAlgorithmTag . Aes128 , "/OCB/NoPadding" , key , iv , secKeyData , 0 , secKeyData . Length ) ;
1356
+ IBufferedCipher c = CipherUtilities . GetCipher ( "AES/OCB" ) ;
1357
+ c . Init ( false , new AeadParameters ( key , 128 , iv , aad . ToArray ( ) ) ) ;
1358
+ data = c . DoFinal ( secKeyData , 0 , secKeyData . Length ) ;
1335
1359
break ;
1336
1360
1337
1361
case "openpgp-native" :
@@ -1344,7 +1368,7 @@ private static byte[] GetDValue(SXprUtilities reader, byte[] rawPassPhrase, bool
1344
1368
//
1345
1369
Stream keyIn = new MemoryStream ( data , false ) ;
1346
1370
1347
- reader = new SXprUtilities ( keyIn ) ;
1371
+ reader = new SXprReader ( keyIn ) ;
1348
1372
reader . SkipOpenParenthesis ( ) ;
1349
1373
reader . SkipOpenParenthesis ( ) ;
1350
1374
reader . SkipOpenParenthesis ( ) ;
0 commit comments