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