diff --git a/README.md b/README.md
index 1bd283ef..30d37323 100644
--- a/README.md
+++ b/README.md
@@ -483,6 +483,8 @@ public void Using_FakerT_Inheritance()
* **`using Bogus.Extensions.Italy;`**
* `Bogus.Person.CodiceFiscale()` - Codice Fiscale
* `Bogus.DataSets.Finance.CodiceFiscale()` - Codice Fiscale
+* **`using Bogus.Extensions.Norway;`**
+ * `Bogus.Person.Fødselsnummer()` - Norwegian national identity number
* **`using Bogus.Extensions.Portugal;`**
* `Bogus.Person.Nif()` - Número de Identificação Fiscal (NIF)
* `Bogus.DataSets.Company.Nipc()` - Número de Identificação de Pessoa Colectiva (NIPC)
diff --git a/Source/Bogus.Tests/ExtensionTests/NorwegianExtensionTest.cs b/Source/Bogus.Tests/ExtensionTests/NorwegianExtensionTest.cs
new file mode 100644
index 00000000..53ea97f8
--- /dev/null
+++ b/Source/Bogus.Tests/ExtensionTests/NorwegianExtensionTest.cs
@@ -0,0 +1,110 @@
+using Bogus.DataSets;
+using Bogus.Extensions.Norway;
+using FluentAssertions;
+using Xunit;
+
+namespace Bogus.Tests.ExtensionTests
+{
+ public class NorwegianExtensionTest : SeededTest
+ {
+ private void IsLegalIndividualNumber(int readIndNo, int birthYear, Person p)
+ {
+ // Check that birth year is in the correct range given individual number.
+ if (0 <= readIndNo && readIndNo <= 499)
+ {
+ birthYear.Should().BeInRange(0, 99);
+ }
+ else if (750 <= readIndNo && readIndNo <= 999)
+ {
+ birthYear.Should().BeInRange(0, 39);
+ }
+ else if (500 <= readIndNo && readIndNo <= 749)
+ {
+ if (0 <= birthYear && birthYear <= 39)
+ {
+ birthYear.Should().BeInRange(0, 39);
+ }
+ else
+ {
+ birthYear.Should().BeInRange(54, 99);
+ }
+ }
+
+ // Check odd/even individual number given gender.
+ if (p.Gender == Name.Gender.Female)
+ {
+ (readIndNo % 2 == 0).Should().BeTrue();
+ }
+ else
+ {
+ (readIndNo % 2 == 0).Should().BeFalse();
+ }
+ }
+
+ private void IsLegalChecksum(string readFødselsnummer)
+ {
+ string readCs = readFødselsnummer.Substring(9, 2);
+
+ int d1 = int.Parse(readFødselsnummer.Substring(0, 1));
+ int d2 = int.Parse(readFødselsnummer.Substring(1, 1));
+ int m1 = int.Parse(readFødselsnummer.Substring(2, 1));
+ int m2 = int.Parse(readFødselsnummer.Substring(3, 1));
+ int y1 = int.Parse(readFødselsnummer.Substring(4, 1));
+ int y2 = int.Parse(readFødselsnummer.Substring(5, 1));
+ int i1 = int.Parse(readFødselsnummer.Substring(6, 1));
+ int i2 = int.Parse(readFødselsnummer.Substring(7, 1));
+ int i3 = int.Parse(readFødselsnummer.Substring(8, 1));
+
+ int cs1 = 11 - (((3 * d1) + (7 * d2) + (6 * m1) + (1 * m2) + (8 * y1) + (9 * y2) + (4 * i1) + (5 * i2) + (2 * i3)) % 11);
+ int cs2 = 11 - (((5 * d1) + (4 * d2) + (3 * m1) + (2 * m2) + (7 * y1) + (6 * y2) + (5 * i1) + (4 * i2) + (3 * i3) + (2 * cs1)) % 11);
+
+ if (cs1 == 11)
+ {
+ cs1 = 0;
+ }
+
+ if (cs2 == 11)
+ {
+ cs2 = 0;
+ }
+
+ $"{cs1}{cs2}".Should().Be(readCs);
+ }
+
+ private void IsLegalFødselsnummer(string readFødselsnummer, Person p)
+ {
+ readFødselsnummer.Should().HaveLength(11);
+
+ int birthYear = int.Parse(readFødselsnummer.Substring(4, 2));
+ int indNo = int.Parse(readFødselsnummer.Substring(6, 3));
+
+ IsLegalIndividualNumber(indNo, birthYear, p);
+ IsLegalChecksum(readFødselsnummer);
+ }
+
+ [Fact]
+ public void can_create_norwegian_fødselsnummer()
+ {
+ var f = new Faker("nb_NO");
+ var person = f.Person;
+
+ string fødselsnummer = person.Fødselsnummer();
+
+ IsLegalFødselsnummer(fødselsnummer, person);
+ }
+
+ [Fact]
+ public void can_create_correct_checksum_1()
+ {
+ // Test fødselsnummer from DSF.
+ IsLegalChecksum("31080700442");
+ }
+
+ [Fact]
+ public void can_create_correct_checksum_2()
+ {
+ // Test fødselsnummer from DSF.
+ IsLegalChecksum("10050050489");
+ }
+ }
+}
diff --git a/Source/Bogus/Extensions/Norway/ExtensionsForNorway.cs b/Source/Bogus/Extensions/Norway/ExtensionsForNorway.cs
new file mode 100644
index 00000000..eed57228
--- /dev/null
+++ b/Source/Bogus/Extensions/Norway/ExtensionsForNorway.cs
@@ -0,0 +1,125 @@
+using System;
+
+namespace Bogus.Extensions.Norway
+{
+ ///
+ /// API extensions specific for a geographical location.
+ ///
+ public static class ExtensionsForNorway
+ {
+ ///
+ /// Norwegian national identity number (fødselsnummer)
+ ///
+ public static string Fødselsnummer(this Person p)
+ {
+ const string Key = nameof(ExtensionsForNorway) + "Fødselsnummer";
+ if (p.context.ContainsKey(Key))
+ {
+ return p.context[Key] as string;
+ }
+
+ /*
+ DDMMYYXXXCC
+ | | | | |--> Checksum
+ | | | |
+ | | | |
+ | | | |-----> Individual number
+ | | |-------> Year (last two digits)
+ | |---------> Month
+ |-----------> Day
+
+ The individual number has to be even for women and odd for men.
+
+ The checksum is calculated with a modulo checksum algorithm.
+ If either of the checksum numbers are 10, the fødselsnummer gets
+ rejected, and a new individual number has to be generated.
+
+ https://www.skatteetaten.no/en/person/national-registry/birth-and-name-selection/children-born-in-norway/national-id-number/
+
+ https://nn.wikipedia.org/wiki/F%C3%B8dselsnummer
+
+ https://github.com/deegane/NINTool/blob/master/backend/src/main/java/com/nin/validation/NorwegianNinValidator.kt
+
+ https://github.com/magnuswatn/fodselsnummer/blob/master/fodselsnummer.py
+ */
+
+ var r = p.Random;
+ string birthDate = $"{p.DateOfBirth:ddMMyy}";
+
+ string individualNumber;
+ string checksum;
+ bool isOkChecksum;
+
+ do
+ {
+ individualNumber = GenerateIndividualNumber(r, p.Gender, p.DateOfBirth.Year);
+ isOkChecksum = GenerateChecksum(birthDate, individualNumber, out checksum);
+ } while (!isOkChecksum);
+
+ string final = $"{p.DateOfBirth:ddMMyy}{individualNumber}{checksum}";
+
+ p.context[Key] = final;
+ return final;
+ }
+
+ private static string GenerateIndividualNumber(Randomizer r, DataSets.Name.Gender gender, int year)
+ {
+ int from;
+ int to;
+
+ if (1854 <= year && year <= 1899)
+ {
+ from = 500;
+ to = 749;
+ }
+ else if (1900 <= year && year <= 1999)
+ {
+ from = 0;
+ to = 499;
+ }
+ else if (2000 <= year && year <= 2039)
+ {
+ from = 500;
+ to = 999;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), $"{nameof(year)} must be between 1854 and 2039.");
+ }
+
+ int individualNumber = gender == DataSets.Name.Gender.Female ? r.Even(from, to) : r.Odd(from, to);
+
+ return individualNumber.ToString("D3");
+ }
+
+ private static bool GenerateChecksum(string birthDate, string individualNumber, out string checksum)
+ {
+ int d1 = int.Parse(birthDate.Substring(0, 1));
+ int d2 = int.Parse(birthDate.Substring(1, 1));
+ int m1 = int.Parse(birthDate.Substring(2, 1));
+ int m2 = int.Parse(birthDate.Substring(3, 1));
+ int y1 = int.Parse(birthDate.Substring(4, 1));
+ int y2 = int.Parse(birthDate.Substring(5, 1));
+ int i1 = int.Parse(individualNumber.Substring(0, 1));
+ int i2 = int.Parse(individualNumber.Substring(1, 1));
+ int i3 = int.Parse(individualNumber.Substring(2, 1));
+
+ int cs1 = 11 - (((3 * d1) + (7 * d2) + (6 * m1) + (1 * m2) + (8 * y1) + (9 * y2) + (4 * i1) + (5 * i2) + (2 * i3)) % 11);
+ int cs2 = 11 - (((5 * d1) + (4 * d2) + (3 * m1) + (2 * m2) + (7 * y1) + (6 * y2) + (5 * i1) + (4 * i2) + (3 * i3) + (2 * cs1)) % 11);
+
+ if (cs1 == 11)
+ {
+ cs1 = 0;
+ }
+
+ if (cs2 == 11)
+ {
+ cs2 = 0;
+ }
+
+ checksum = $"{cs1}{cs2}";
+
+ return cs1 < 10 && cs2 < 10;
+ }
+ }
+}
\ No newline at end of file